Прототип 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 не является.