Страницы

Поиск по вопросам

суббота, 7 декабря 2019 г.

В чем отличие __proto__ от prototype?

#javascript #прототипное_наследование


В чем различие этих 2 способов прототипного наследования и какой из них более правильнее
использовать?



function Cat() {
    this.__proto__.type = 'кот';
}


var cat = new Cat();
console.log(cat.type); // кот


function CatTwo() {
}
CatTwo.prototype.type = 'тоже кот';

var catTwo = new Cat();
console.log(catTwo.type); // тоже кот



    


Ответы

Ответ 1



На самом деле в примере в вопросе нет наследования. __proto__ до недавнего времени не был стандартизирован. В последних спецификациях можно найти, что getter __proto__, обертка над вызовом внутренней функции [[GetPrototypeOf]]. Точно такая же, как и функция Object.getPrototypeOf Если применительно к приведенному коду: в первом случае значение прототипа меняется каждый раз при создании объекта, во втором - устанавливается всего один раз. Отсюда можно сделать вывод, что если есть доступ к конструктору, прототип лучше менять непосредственное у него. Пример, когда приведенный код выдаст разные значения: function Cat(type) { this.__proto__.type = type; } var cat = new Cat('кот'); console.log(cat.type); // кот var cat2 = new Cat('кот2'); console.log(cat.type); // кот2 console.log(cat2.type); // кот2 function CatTwo() {} CatTwo.prototype.type = 'тоже кот'; var catTwo = new CatTwo(); console.log(catTwo.type); // тоже кот

Ответ 2



Свойство __proto__ Абсолютно любой объект в JavaScript имеет свойство proto. Это скрытое системное свойство, и не во всех реализациях языка оно доступно пользователю. При обращении к любому свойству объекта, оно в первую очередь ищется в самом объекте: var obj = {ownProperty: 1}; console.log(obj.ownProperty);// 1 Но если его там нет, поиск происходит в свойстве proto: obj.__proto__ = {propertyOfProto: 2}; console.log(obj.propertyOfProto);// 2 Если его нет и там, оно ищется дальше по цепочке: obj.__proto__.__proto__ = {propertyOfProtosProto: 3}; console.log(obj.propertyOfProtosProto);// 3 Эта цепочка называется цепочкой прототипов (prototype chain). proto любого значения (кроме null и undefined) ссылается на prototype соответствующего ему типу данных: (0).__proto__ === Number.prototype false.__proto__ === Boolean.prototype "string".__proto__ === String.prototype (new Date).__proto__ === Date.prototype (function(){}/* new Function */).__proto__ === Function.prototype Все типы данных наследуются от Object, это означает что: Number.prototype.__proto__ === Object.prototype И наконец, завершение цепочки: Object.prototype.__proto__ === null Свойство prototype Это обычное свойство, ничем не отличающиеся от любых других свойств. За исключением двух особенностей: 1) Функции в JavaScript имеют свойство prototype. Оно по умолчанию является объектом с единственным свойством constructor, которое ссылается на саму функцию. 2) Свойство prototype используется при создании новых объектов оператором new. Этот оператор делает следущее: Создает пустой объект: var instance = {}; Устанавливает proto этому объекту ссылкой на prototype функции-класса: instance.__proto__ = FnClass.prototype; Применяет функцию-класс к нашему новосозданному объекту: constructorReturns = FnClass.apply(instance, arguments); т.е. исполняет функцию FnClass, передавая ей instance в качестве this и аргументы в виде массива arguments. Возвращает экземпляр функции-класса, но если FnClass нам вернул обьект, тогда его: return constructorReturns instanceof Object ? constructorReturns : instance; Функцией-классом я называю функцию, к которой впоследствии ожидается применение оператора new. Такие функции принято именовать с заглавной буквы.

Комментариев нет:

Отправить комментарий