2014-01-15 4 views
2

Попытка понять прототипы в Javascript. Для этого примера:Лучший способ получить прототип объекта JS

var obj = new Function(); 
obj.prototype.x = "a"; 

Почему я получаю разные результаты

console.log(obj.__proto__); 

и

console.log(obj.prototype); 

Благодарности

+0

proto == contructor.prototype – dandavis

+0

Возможный дубликат [Что означает это предложение: «Другими словами, obj.proto тип вообще не является объектом {Prototype} объекта obj. "] (http://stackoverflow.com/questions/21075114/what-does-this-sentence-mean-in-other-words-obj-prototype-is-in- general-not-t), [Почему это поведение? __ proto__ vs prototype?] (http://stackoverflow.com/q/16394709/1048572) и в основном [__proto__ Vs. прототип в JavaScript] (http://stackoverflow.com/q/9959727/1048572) – Bergi

ответ

2

В:

> var obj = new Function(); 

новая функция создается объект, внутренний [[Prototype]] (или __proto__ в браузерах, которые поддерживают его) ссылается Function.prototype, то есть встроенные функции конструктора public prototype и присваивается переменной OBJ ,

Поскольку OBJ является объектом Function, он имеет прототип свойство по умолчанию только в случае, если она будет использоваться в качестве конструктора.

В:

> obj.prototype.x = "a"; 

новое свойство х добавляется obj.prototype, которому присваивается значение строки 'a'. Обратите внимание, что obj имеет свойство prototype по умолчанию, потому что это объект Function.

Итак:

obj.prototype === obj.__proto__ 

по существу:

obj.prototype === Function.prototype 

, который явно ложно.

Таким образом, чтобы ответить на вопрос «Лучший способ получить прототип объекта JS», вы можете обратиться к публичному прототипу конструктора через свой прототип .

Вы можете получить доступ к внутреннему экземпляру экземпляра [[Prototype]] с использованием ES5 Object.getPrototypeOf, однако он может не поддерживаться повсеместно.

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

Более общее решение сохранить ссылку на прототип конструктора в момент создания экземпляра (так как изменения прототипа конструктора на более позднем этапе не изменят [[Prototype]] экземпляров, которые уже были созданы).

Таким образом, в общем случае вы можете сделать:

function Foo() { 
    this.internalProto = Foo.prototype; 
} 

var foo = new Foo(); 

// ES5, where supported 
Object.getPrototypeof(foo) == Foo.prototype; // true 

foo.internalProto == Foo.prototype; // true 

// Non–standard, Where supported 
foo.internalProto == foo.__proto__;  // true 
0

Accordint к MDN, OBJ .__ proto__ не были стандартизированы ,

Таким образом, хотя obj.prototype имеет четкое стандартизованное поведение в браузерах, obj .__ proto__ ведет себя по-разному в разных браузерах.

+1

Да, но это не отвечает на вопрос, то есть почему fnObj.prototype! == fnObj [[Prototype]] '. – RobG

2

Согласно этому источнику: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

Object.prototype.__proto__ указывает на объект, который был использован в качестве прототипа , когда объект был экземпляр.

Это просто означает, что объект, используемый в качестве прототипа для создания объекта функции, был пустой функцией, и именно поэтому у вас есть вывод function Empty() {}. Вы можете наблюдать его здесь:

console.log(Function.prototype); 
var func = new Function(); 
console.log(func.__proto__); 
console.log(func.prototype); 
// OUTPUT: 
// function Empty() {} 
// function Empty() {} 
// Object {} 

__proto__ пустого объекта (например, var a = {}) является Object {}, потому что это то, что было использовано для создания базы вашего объекта (другими словами Object.prototype был использован). И prototype даже не доступен как свойство a, потому что вы создали абсолютно пустой объект, так что ничего нет.

Также обратите внимание, что __proto__ сейчас устарел.

Почему? Я не знаю, но я никогда не использовал его, поэтому мне все равно :)

prototype - это другое дело, например.

Изменения в Object prototype object распространяются на все объекты , если свойства и методы С учетом этих изменений не преодолено дальше по цепочке прототипов.

Вот почему вам нужно prototype, и вы не заботитесь о __proto__ в реальной жизни. Если я ошибаюсь, покажите мне полезное использование __proto__.

Надеюсь, теперь это яснее. И чтобы ответить на ваш первоначальный вопрос:

Прототип объекта JS можно получить только с использованием свойства prototype, так как __proto__ содержит sth different. Если свойство prototype не существует, прототипа объекта JS нет, даже если sth использовался в процессе создания экземпляра.

+1

Я считаю, что '__proto__' устарел, потому что он никогда не был стандартизирован и имеет замену, которая является частью стандарта: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf – Paulpro

+0

Вы правы - только что проверили это - он делает то же самое, что и '__proto__', но он устарел:' var func = new Function(); console.log (func .__ proto__); console.log (Object.getPrototypeOf (func)); console.log (func.prototype); ' – Karol

0

Вы смотрите на это боком ...

.prototype и .__proto__ являются тем же объектом (или находятся в одной конкретной точке во время) ...

BUUUUUT они propertes из разные объектов.

var Human = function (name) { 
    this.num_eyes = 2; 
    this.num_heads = 1; 
    this.name = name; 
}; 
Human.prototype.die = function() { this.isAlive = false; }; 

var herman = new Human("Herman"); 

herman.__proto__.die === Human.prototype.die; // true 

.__proto__ является ссылка на КОНСТРУКТОРСКИМИ .prototype (и, как правило, является и тот же объект)

Это почти так:

var Human = function() { 
    this = {}; 
    this.num_eyes = 2; 
    // ...... 
    this.__proto__ = Human.prototype; 
}; 

Это не точно как Конструкторы работа, но на самом деле, это идея.
И вот почему .__proto__ и .prototype не то же самое.
Потому что вы ищете не то место.

Так что если:

var herman = new Human(); 
herman.__proto__ === Human.prototype; 
var Human = new Function(); 

... так логика затем утверждает, что Human.__proto__ === Function.prototype;

... и если Human и Function не тот же объект, то их .prototype свойства не будут (если вы не перепишете его с другим Human.prototype = Function.prototype; Human.__proto__ === Human.prototype; //true

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