Прототипы и создание объектов - PullRequest
3 голосов
/ 28 сентября 2011

В последнее время я пытаюсь понять технические аспекты цепочки прототипов.Теперь у меня есть несколько вопросов об экземпляре объекта.

Рассмотрим следующий код:

var Foo = function(s) {
  this._bar = s;
};

var fooInst = new Foo('test');

Теперь, когда я проверяю созданный объект, тогда:

Foo.prototype === Function.prototype; // true

fooInst.prototype === ?
fooInst.prototype.prototype === Object.prototype; // true

Iмне интересно, что же такое fooInst.prototype.В инспекторе Chromes это похоже на Foo со свойством constructor.Но все источники, которые я читал о прототипах, утверждают, что fooInst.prototype === Foo.prototype должно быть правдой.

Поэтому мой вопрос: как именно JS обрабатывает цепочку прототипов.Что именно происходит, когда я звоню new Foo.

Заранее спасибо!

Редактировать

Итак, я обнаружил, что (в Chrome) Object.getPrototypeOf(fooInst) === Foo.prototype; равно true, но Object.getPrototypeOf(fooInst) === Object.getPrototypeOf(Foo) равно false.Почему это?

Ответы [ 3 ]

6 голосов
/ 28 сентября 2011

Мне интересно, что именно за fooInst.prototype.

Это undefined.

fooInst.prototype === undefined; // true

Только функции имеют автоматическое свойство .prototype.Объекты этого не делают.

Если вы создаете объект с помощью конструктора, например:

var fooInst = new Foo('test');

... тогда fooInst будет иметь внутреннюю ссылку на Foo.prototype, но нет стандартное свойство для получения Foo.prototype из fooInst.


Тем не менее, существует нестандартное свойство, которое поддерживается в некоторые среды JavaScript для ссылки на объект-прототип.

fooInst.__proto__ === Foo.prototype; // true (if __proto__ supported)

Также существует метод , предоставляемый ECMAScript 5 , который можно использовать.

Object.getPrototypeOf( fooInst ) === Foo.prototype;  // true

Эта внутренняя ссылка от объекта на его объект-прототип может быть только первой в цепочке таких ссылок.

Объект-прототип, скорее всего, имеет свой собственный объект-прототип, на который есть ссылка. (В основных случаях это будет Object.prototype, или с более длинными цепями, Object.prototype может быть дальше по цепочке.)

Object.prototype сама ссылается на null какпрототип.Это завершает цепочку.

Следует отметить, что внутренняя ссылка от объекта на его объект-прототип не изменится, если вы измените объект .prototype функции конструктора.Это ссылка, которая существует для жизни объекта.

var Foo = function(s) {
  this._bar = s;
};

var fooInst = new Foo('test');

Object.getPrototypeOf( fooInst ) === Foo.prototype;  // true

// Change the prototype object of Foo
Foo.prototype = { some:'object' };

Object.getPrototypeOf( fooInst ) === Foo.prototype;  // false
2 голосов
/ 28 сентября 2011

Ваше первое предположение:

Foo.prototype === Function.prototype;

Неправильно, я думаю, что вы путаете концепцию внутреннего свойства [[Prototype]], которое есть у всех объектов, и создаете «звено» цепочки прототипов, а также свойство prototype, которое есть у функциональных объектов.

Приведенное выше сравнение даст false, поскольку значением свойства Foo.prototype является новый объект, созданный во время создания функции Foo.

Этот объект инициализируется всякий раз, когда вы создаете объект функции, он наследует от Object.prototype и имеет свойство с именем constructor, которое указывает на функцию (Foo.prototype.constructor === Foo), и используется при вызове вашей функции как конструктор.

Теперь, если мы говорим о внутреннем свойстве [[Prototype]], вы правы, [[Prototype]] вашей функции Foo равен Function.prototype Другими словами, Foo наследуется от Function.prototype, например:

Object.getPrototypeOf(Foo) === Function.prototype; // true
Foo instanceof Function; // true
Foo.__proto__ === Function.prototype; // true

О fooInst этот объект был создан в новом выражении , когда вы использовали функцию Foo в качестве конструктора, этот новый объект создается, и он наследует от Foo.prototype, (его внутреннее [[Prototype]] свойство указывает на Foo.prototype).

У него нет свойства prototype, поскольку это свойство имеет смысл только для функциональных объектов.

Смотри также:

1 голос
/ 28 сентября 2011

Вы можете найти объяснения и диаграммы в JavaScript. Ядро полезно здесь.

Все объекты имеют цепочку прототипов. Таким образом, fooInst имеет цепочку прототипов, во главе которой стоит Foo.prototype. Когда вы вызывали new Foo, объект был создан, Foo.prototype был задан в качестве цепочки прототипов, и функция конструктора была вызвана в контексте нового объекта.

Некоторые браузеры предоставляют это как нестандартное свойство __proto__, например:

fooInst.__proto__ === Foo.prototype
...