Прототип Javascript через Object.create()
var someObj = function() { }
var p = new someObj();
alert(someObj.prototype); // This works
alert(p.prototype); // UNDEFINED, but why?
someObj.prototype.model= "Nissan";
alert(p.model); // This works! I understand the dynamic nature of prototypes, but doesn't that mean that p.prototype === someObj.prototype?
Почему это так? Поскольку "p" является экземпляром "someObj", почему прототип undefined? Я имею в виду, когда я добавляю свойство прототипу "someObj", он доступен для "p", поэтому почему прототип недоступен?
Ответы
Ответ 1
Важно то, что свойство prototype
объектов функции не является прототипом объекта. Это объект, который будет назначен прототипом объекта, создаваемого с помощью new someObj
. До ES5 вы не можете напрямую обращаться к прототипу объекта; с ES5 вы можете, используя Object.getPrototypeOf
.
Re
alert(p.prototype); // UNDEFINED, but why?
Причина в том, что объект p
не имеет свойства, называемого "prototype". Он имеет базовый прототип, но это не то, как вы к нему обращаетесь.
Все объекты функций имеют свойство prototype
, поэтому, если они используются как функции конструктора, мы можем определить, какие будут свойства базового прототипа объектов, созданных этими конструкторами. Это может помочь:
function Foo() {
}
Foo.prototype.answer = 42;
console.log(Foo.prototype.answer); // "42"
var f = new Foo();
console.log(f.answer); // "42"
Эта последняя строка работает следующим образом:
- Получить объект
f
.
- У
f
есть собственное свойство , называемое "ответ"?
- Нет, у
f
есть прототип?
- Да, у прототипа есть свое собственное свойство, называемое "ответ"?
- Да, верните значение этого свойства.
Вы упомянули Object.create
в названии своего вопроса. Важно понимать, что Object.create
совершенно отделен от функций конструктора. Он был добавлен к языку, так что, если вы предпочитаете не использовать функции конструктора, вам не нужно было, но он мог бы установить прототип объекта — непосредственно, когда вы создаете этот объект.
Ответ 2
Это потому, что prototype
является свойством функции-конструктора, а не его собственностью. Однако объект prototype
имеет ссылку на конструктор, поэтому вы можете получить доступ к объекту prototype
через его свойство constructor
:
function Foo() {}
Foo.prototype.foo = "bar";
var c = new Foo;
console.log( c.constructor === Foo ); // true
console.log( c.constructor.prototype ); // { foo: 'bar' }
Однако это не сработает, если вы перезапишите начальное свойство prototype
функции конструктора:
function Foo() {}
// I overwrite the prototype property, so I lose the initial reference
// to the constructor.
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
Вот почему вам лучше использовать новый Object.getPrototypeOf
метод, введенный в ES5.
function Foo() {}
Foo.prototype = {
foo: "bar"
};
var c = new Foo;
console.log( c.constructor === Foo ); // false
console.log( c.constructor === Object ); // true
console.log( c.constructor.prototype ); // {}
console.log( Object.getPrototypeOf(c) ); // { foo: 'bar' }
Другим решением было бы убедиться, что вы восстановили ссылку constructor
на прототипе:
function Foo() {}
// Overwriting the initial prototype
Foo.prototype = {
constructor: Foo, // restore the constructor reference
foo: "bar"
};
Ответ 3
p.prototype не работает, потому что в этом случае p = someObj.prototype.
В основном, когда вы используете новый оператор, случается, что конструктор someObj используется для инициализации нового объекта. Это означает, что он возвращает объект, который имеет свойства и методы прототипа конструктора.
Таким образом, p = someObj.prototype и p.prototype undefined, поскольку p не является конструктором.
Эта статья может помочь объяснить это больше
http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD
Ответ 4
p
является экземпляром someObj
. Прототип принадлежит конструктору. Вы можете получить прототип конструктора p
с помощью p.constructor.prototype
Ответ 5
В Javascript, конструкторы, и фактически все функции получают свойство прототипа. Объекты (т.е. Набор пар ключ-значение) не имеют свойства прототипа. В приведенном выше примере
var someObj = function() { } // this is a function, so it has a prototype property
var p = new someObj(); // this is an instance object, so it doesn't
Вот почему someObj.prototype определен, но p.prototype не является.