Ошибки обращения к методам прототипа

280
13 июля 2018, 17:30

Есть такой код:

'use strict' 
var collectionProto = { 
  values: function() { 
    return this; 
  }, 
  count: function() { 
    return this.length; 
  }, 
  at: function(index) { 
    return (index > this.length) ? this[index - 1] : null; 
  }, 
  append: function(value) { 
    (isArray(value)) ? this.concat(value): this.push(value); 
  }, 
  removeAt: function(index) { 
    if (index > this.length) { 
      return false; 
    } 
    this.splice(index - 1, 1); 
    return true; 
  } 
}; 
 
function Collection() { 
  //this = []; 
  return []; 
} 
Collection.prototype = collectionProto; 
Collection.prototype.constructor = Collection; 
 
var numbers = new Collection(); 
console.log(numbers.values());

Собственно, сама ошибка

TypeError: numbers.values is not a function

И два вопроса:

  1. Почему вылазит ошибка?
  2. Почему нельзя написать в конструкторе this = []? Ведь this здесь объект, который создаёт интерпретатор по умолчанию.
Answer 1
  1. Вы же возвращаете массив, а не создаваемый конструктором объект.
  2. this - служебная конструкция, её нельзя переопределять. Да и какой в этом смысл?

'use strict' 
var collectionProto = { 
    answer: 42 
}; 
 
function Collection() { 
  this.question = 'The Ultimate Question of Life, the Universe, and Everything'; 
} 
Collection.prototype = collectionProto; 
Collection.prototype.constructor = Collection; 
 
var numbers = new Collection(); 
console.log(numbers.question, numbers.answer);

Answer 2

Когда ты возвращаешь объект из конструктора, созданный объект забывается. Поэтому (при отсутствии ES6) можно заменить __proto__ (поддерживается в IE11+):

'use strict' 
 
var collectionProto = Object.assign(Object.create(Array.prototype), { 
  values: function() { 
    return this; 
  }, 
  count: function() { 
    return this.length; 
  }, 
  at: function(index) { 
    return (index > this.length) ? this[index - 1] : null; 
  }, 
  append: function(value) { 
    (isArray(value)) ? this.concat(value): this.push(value); 
  }, 
  removeAt: function(index) { 
    if (index > this.length) { 
      return false; 
    } 
    this.splice(index - 1, 1); 
    return true; 
  } 
}); 
 
function Collection() { 
  var me = []; 
  me.__proto__ = this.__proto__; 
  return me; 
} 
 
Collection.prototype = collectionProto; 
Collection.prototype.constructor = Collection; 
 
var numbers = new Collection(); 
console.log(numbers.values());

Answer 3

'use strict' 
var collectionProto = { 
  values: [], 
  count: function() { 
    return this.values.length; 
  }, 
  at: function(index) { 
    return (index > this.values.length) ? this.values[index - 1] : null; 
  }, 
  append: function(value) { 
    Array.isArray(value) ? this.values.concat(value): this.values.push(value); 
  }, 
  removeAt: function(index) { 
    if (index > this.values.length) { 
      return false; 
    } 
    this.values.splice(index - 1, 1); 
    return true; 
  } 
}; 
 
function Collection() {} 
Collection.prototype = collectionProto; 
Collection.prototype.constructor = Collection; 
 
var numbers = new Collection(); 
console.log(numbers.values); 
 
numbers.append(6757); 
console.log(numbers.values);

READ ALSO
Проблема с heroku

Проблема с heroku

Пытаюсь выставить приложение на сервер heroku,но не получается,делаю всё как по инструкции

304
Скачивание файлов с напрямую API

Скачивание файлов с напрямую API

Есть сайт и API, написанные на ASPNET Core

251
проблемы с vue-croppie.js на mobile

проблемы с vue-croppie.js на mobile

Всем доброго времени суток, возникли проблемы с использованием vue-croppiejs

248