Ответ 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
...