2015-07-10 3 views
7

Из того, что я знаю, функция должна наследовать свойства от объекта prototype, к которому можно получить доступ, используя .prototype или __proto__.__proto__ и разница между прототипом

//my prototype Object 
var myObj = { 
    a: 1, 
    b: 2 
}; 

var myFunc = function() {}; 

// setting function's `prototype` property 
myFunc.prototype = myObj; 
alert(myFunc.a); 
//returns undefined (Why???) I was expecting 1 

Но когда я попытался следующие,

//setting function __proto__ property 
myFunc.__proto__ = myObj; 
//returns 1 
alert(myFunc.a); 

Так почему это работает, когда я установил myFunc.__proto__ и не тогда, когда я установил myFunc.prototype?

Я действительно ссылался на __proto__ VS. prototype in JavaScript, но не мог понять.

+2

http://es5.github.io/ ничего не знает о '__proto__' вообще. Это означает, что он не является частью стандарта, и вы никогда не должны его использовать. – zerkms

+0

Нет, прототип объекта (тот, который он наследует) - это ** не ** '.prototype'. Вы прочитали все ответы на http://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript? Что конкретно вы не поняли (мы рады их улучшить)? – Bergi

+0

то что такое .prototype, используемый для ?? – Flake

ответ

15

__proto__

Вы действительно можете получить доступ к внутреннему [[Prototype]] свойства объекта с __proto__. Вы можете представить [[Prototype]] как фактический родитель текущего объекта в иерархии наследования.

prototype

Это особое свойство, когда установлено на функцию (конструктор) объекта, используемого для установления цепи наследования для экземпляров, созданных из конструктора. Например,

function Foo() {} 
Foo.prototype = {a: 1}; 

Теперь, когда вы создаете новый объект типа Foo, внутренняя [[Prototype]] собственности вновь созданный объект будет ссылаться на Foo.prototype объекте. Вы можете подтвердить, что как этот

console.assert((new Foo()).__proto__ === Foo.prototype); 

В вашем случае,

myFunc.prototype = myObj; 

вы создаете prototype свойство на объекте функции, и это будет использоваться только при создании новых объектов с эта функция (функция конструктора). Вы можете подумать об этом как о шаблоне для новых объектов. Итак, когда вы делаете myFunc.a, JS-движок пытается найти a в myFunc и его родителям в цепочке прототипов, и он не находит его, поэтому он возвращает undefined.

Но, когда вы делаете

myFunc.__proto__ = myObj; 

вы устанавливаете родительский myFunc в цепочке прототипов, чтобы myObj. Итак, когда вы делаете myFunc.a, JS-движок сначала пытается найти a в myFunc самом объекте, и его там нет. Таким образом, он пытается найти его у своего непосредственного родителя, который равен myObj. Поэтому в этом случае он возвращает 1.


Примечание: Вы можете использовать следующую функцию, чтобы понять цепочку прототипов лучше

function printPrototypeChain(object) { 
    while (object !== null) { 
     console.log(object); 
     object = Object.getPrototypeOf(object); 
    } 
} 

Теперь, давайте печатать цепочку прототипов, когда объект установлен как prototype свойства функции объект.

function myFunc() {} 
myFunc.prototype = { 
    a: 1, 
    b: 2 
}; 
printPrototypeChain(myFunc); 

Вывод будет

[Function: myFunc] 
[Function: Empty] 
{} 

Ни один из этих объектов не имеют определенного a, поэтому undefined возвращается. Но, в этом случае,

function myFunc() {} 
myFunc.__proto__ = { 
    a: 1, 
    b: 2 
}; 
printPrototypeChain(myFunc); 

прототип цепь становится как этого

[Function: myFunc] 
{ a: 1, b: 2 } 
{} 

и a находится в непосредственном родителе myFunc «s. Таким образом, возвращается соответствующее значение 1.

Примечание: Не используйте __proto__ в вашем фактическом коде, так как он сохранен в последних версиях спецификации JavaScript только для обратной совместимости. Узнайте больше об этом here. Вместо этого используйте Object.getPrototypeOf и Object.setPrototypeOf.

+1

два прототипа для функции ...... dats confusing !!! – Flake

+0

Когда вы делаете myFunc.prototype = myObj; myObj доступен для экземпляров myFunc, а не для myFunc. var x = new myFunc(); console.log (x.a); // возвращает 1 – prgmrDev

0

Вы вводите в заблуждение myFunc, который является конструктором, с примером от myFunc.

Если вы что-то вроде этого:

var o = new myFunc(); 
alert(o.a); 

Это предупредит 1, потому что o является экземпляром myFunc, поэтому его свойство a исходит от myFunc прототипа.

Если вы установили __proto__, вы буквально замените прототип функции, который myFunc наследовал от ранее и заменил его на свой прототип объекта. Фактически, после того, как вы это сделаете, любые методы, которые вы обычно можете использовать для функций, таких как call, больше не будут найдены на myFunc.

myFunc.__proto__ = myObj; 
myFunc.call(null); // Will throw an error 
0

Все объекты JS имеют __proto__ системное свойство. Если вы попытаетесь получить значение x значения объекта a, это, прежде всего, поиск этого объекта среди объектов a. Если ничего не найдено, свойство будет искать среди a.__proto__ peroperties. И так далее. Вот почему myFunc.a руткин 1 в вашем примере. При установке myFunc.prototype=myObj, что означает, что myObj будет использоваться в будущем при создании экземпляров myFunc:

var mf = new myFunc(); 

и это вовсе не означает, что myFunc должен иметь a самого protpery, как я уже говорил выше.

Смежные вопросы