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

Разница между Object.create(Object.prototype), Object.create(Object) и Object.create(null)

Какой параметр должен передать первый родительский объект, из которого другие наследуют, а какой более эффективный

Object.create(Object.prototype)

Object.create(Object)

Object.create(null)  

Object.create(null) возвращает пустой объект

Object.create(Object) возвращает функцию, почему???? (я проверил свой журнал, и он говорит, что функция... я использовал console.dir())

Object.create(Object) возвращает непустой объект

Как все это работает... Я больше привык к объекту Classname.prototype: (

Не могу понять, что здесь происходит.

4b9b3361

Ответ 1

Предисловие: JavaScript использует прототип наследования, что означает, что объект может иметь (как правило, имеет) прототип за ним, который является другим объектом. Если вы попытаетесь получить значение свойства от объекта, которого у него нет, механизм JavaScript ищет прототип объекта (и его прототип и т.д.), Чтобы найти его.

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

// Create an object with a property 'foo'
var a = {
    foo: 42
};

// Create a blank object using 'a' as its prototype
var b = Object.create(a);

// Give 'b' a property of its own
b.bar = "hi";

Это дает нам это в памяти:

                           +−−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−+
                           | [[Prototype]] |−−−−−>| (the standard     |
a−−−−−−−−−−−−−−−−−−−−−−+−−>| foo: 42       |      | object prototype) |
                       |   +−−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−+   
                       |
    +−−−−−−−−−−−−−−−+  |
b−−>| [[Prototype]] |−−+
    | bar: "hi"     |
    +−−−−−−−−−−−−−−−+

В доказательстве b используется a:

console.log(b.foo); // 42
a.foo = 67;
console.log(b.foo); // 67

Обращаясь к некоторым из ваших вариантов:

var o = Object.create(Object.prototype);

Это точно так же, как var o = {};: создается новый пустой объект, прототип которого является ссылкой на объект Object.prototype.

var o = Object.create(Object);

Это создает новый пустой объект o, прототипом которого является функция Object. Он не создает функцию, а просто нефункциональный объект, у которого функция является его прототипом. Это было бы довольно странно и, вероятно, не то, что вы хотите. :-)

var o = Object.create(null);

Создает новый пустой объект o, прототип которого - null. Поскольку его прототипом является null, он не имеет обычных вещей Object.prototype, таких как toString и valueOf и hasOwnProperty. Это немного необычно, хотя для этого есть варианты использования, например, когда вы используете объект в качестве словаря/карты и не хотите ложных срабатываний для этих имен свойств. (В ES2015 [aka ES6] другой вариант - использовать вместо него Map.)


Как указывает thg435 в комментарии ниже, одна из запутанных вещей в JavaScript заключается в том, что прототип объекта совершенно отличается от свойства prototype, которое вы видите в функциях. Вероятно, было бы лучше, если бы свойство prototype имело другое имя (хотя я не могу себе представить, каким оно будет, если оно не очень громоздкое).

Объект (пусть назовем его o) имеет объект-прототип, от которого он наследует свойства. (В ES2015+ вы можете получить доступ к этому объекту через Object.getPrototypeOf.) Объект в свойстве функций prototype вовсе не обязательно является прототипом какого-либо объекта. Вместо этого это объект, который будет назначен в качестве прототипа любого объекта, созданного с помощью new с использованием этой функции.

Примеры помогают здесь.

function Foo() {
}

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

var f = new Foo();

Теперь этот объект используется в качестве прототипа, в частности, это прототип объекта f, созданного с помощью вызова new Foo.

Игнорируя несколько деталей, эта строка кода:

var f = new Foo();

... в основном это делает:

// Create a blank object, giving it 'Foo.prototype' as its prototype
var f = Object.create(Foo.prototype);

// Call' Foo' using that new object as 'this'
Foo.call(f);

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

Ответ 2

То, что возвращается, является объектом.

>>> typeof Object.create(Object)
<<< "object"
>>> Object.create(Object)
<<< Function {}
//           ^^

Function - это имя, которое Chrome адресует конструктору объекта. См. Как имена классов javascript вычисляются для пользовательских классов в инструментах Chrome Dev?


Эта часть ответа адресует @phenomnomnominal комментарий в вопросе, объясняя, почему созданный объект наследует свойства функции, такие как call.

Конструктор Object является функцией и, таким образом, наследуется от прототипа Function:

>>> Object.call === Function.prototype.call
<<< true

Таким образом, объект, имеющий Object в качестве прототипа, будет иметь ссылку на прототип Function через цепочку прототипов:

>>> Object.create(Object).call === Function.prototype.call
<<< true

И, как упоминалось в @TJ, использование конструктора в качестве прототипа довольно странно. Вы должны указать объект как прототип, из которого наследуется созданный объект. @TJ уже проделала довольно хорошую работу, объясняя эту часть.