В чем различие этих 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); // тоже кот
На самом деле в примере в вопросе нет наследования.
__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); // тоже кот
Свойство __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. Такие функции принято именовать с заглавной буквы.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Проблема в чём, не применяются свойства плагина mmenuВроде бы подписал всё правильно, и в index
Здравствуйте, уважаемые коллеги! Осваиваю Spring MVC уверенными шагами, но есть один вопрос на который не могу найти внятного ответаВ данный момент...