Подтвердить что ты не робот

Новый объект в Javascript имеет свойство прототипа?

Это чисто тривиальный вопрос для академической ценности:

Если я создаю новый объект, либо сделав:

var o = { x:5, y:6 };

или

var o = Object.create({ x:5, y:6 });

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

Кроме того, вызов toString() (метод Object.prototype) на этом объекте работает просто отлично, подразумевая, что o наследует от Object.prototype. Так почему я получаю undefined?

4b9b3361

Ответ 1

Существует различие между экземплярами и их конструкторами.

При создании объекта типа {a: 1} вы создаете экземпляр конструктора Object. Object.prototype действительно доступен, и все функции внутри этого прототипа доступны:

var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true

Но Object.create делает что-то другое. Он создает экземпляр (объект), но вставляет дополнительную цепочку прототипов:

var o = {a: 1};
var p = Object.create(o);

Цепочка будет:

Object.prototype  -  o  -  p

Это означает, что:

p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true

Чтобы получить прототип "под" экземпляра, вы можете использовать Object.getPrototypeOf:

var o = {a: 1};
var p = Object.create(o);

Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true

(Раньше вы могли получить доступ к прототипу экземпляра с помощью o.__proto__, но это было устарело.)

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

o.constructor === Object; // true

Итак:

o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true

Это не выполняется для Object.create -созданных объектов, потому что у них нет конструктора (вернее, их конструктор Object, а не то, что вы передали в Object.create, потому что функция конструктора отсутствует).

Ответ 2

Не прямой ответ, но знание о том, что все, кто имеет дело с наследованием в Javascript, должны иметь.

Наследование прототипа в Javascript - сложная концепция. До сих пор было невозможно создать пустой объект (пустым я имею в виду, что даже объекты не имеют объектов с помощью прототипа). Таким образом, это означает, что при создании нового объекта всегда была ссылка на исходный прототип объекта. Однако, согласно спецификации, цепочка прототипов экземпляра объекта не видна, но некоторые поставщики решили реализовать свои собственные свойства свойств объекта, чтобы вы могли следить за ним, но настоятельно рекомендуется не использовать его в производственном коде.

Следующий пример кода демонстрирует только два способа создания экземпляра объекта.

var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});

Даже если вы не добавляете вручную свойства объекта для пустых фигурных скобок, вы все равно получаете автоматически добавленную цепочку прототипов. То же самое касается второго примера. Чтобы визуализировать это лучше, вы можете ввести эти строки в консоль Chrome, а затем ввести someObject, otherObject или thirdObject, чтобы просмотреть детали. Chrome показывает цепочку прототипов, добавив проприетарное свойство __proto__, которое вы можете развернуть, чтобы увидеть, что унаследовано и откуда оно. Если вы выполнили что-то вроде

Object.prototype.sayHello = function() {
  alert('hello');
};

вы могли бы вызвать его во всех экземплярах, выполнив otherObject.sayHello().

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

var emptyObject = Object.create(null);

Когда вы вводите его в консоль Chrome, а затем расширяете emptyObject, чтобы увидеть цепочку прототипов, вы можете видеть, что он не существует. Поэтому, даже если вы внедрили функцию sayHello в прототип объекта, было бы невозможно вызвать emptyObject.sayHello(), поскольку emptyObject не наследуется от прототипа объекта.

Надеюсь, что это поможет с общей идеей.

Ответ 3

JavaScript имеет два типа объектов: объект функции и не-функциональный объект. По идее, все объекты имеют прототип (НЕ ПРОТОТИПНАЯ СОБСТВЕННОСТЬ). Внутренне JavaScript называет прототип объекта как [[Прототип]].

Существует два подхода к получению любого объекта (включая не-функциональный объект) [[prototype]]: метод Object.getPrototypeOf() и __proto__ имущество. Свойство __proto__ поддерживается многими браузерами и Node.js. Он должен быть стандартизован в ECMAScript 6.

Только объект функции (вызываемый) имеет свойство прототипа. Это свойство прототипа является регулярным свойством, которое не имеет прямого отношения к функции own [[prototype]]. При использовании в качестве конструктора (после нового оператора) свойство прототипа функции будет присвоено [[Prototype]] вновь созданного объекта. В не-функциональном объекте свойство прототипа undefined. Например,

var objectOne = {x: 5}, objectTwo = Object.create({y: 6});

Оба объекта ObjectOne и objectTwo являются нефункциональными объектами, поэтому они не имеют свойства прототипа.