通过Object.create()的Javascript原型

Tah*_*mad 10 javascript prototype

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?
Run Code Online (Sandbox Code Playgroud)

为什么会这样?由于"p"是"someObj"的一个实例,为什么原型未定义?我的意思是,当我向"someObj"原型添加属性时,它可以被"p"访问,那么为什么原型不可访问?

T.J*_*der 11

这里重要的是prototype函数对象的属性不是对象的原型.它将被指定为您创建的对象原型的对象new someObj.在ES5之前,您无法直接访问对象的原型; 从ES5开始,你可以通过Object.getPrototypeOf.

回覆

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"
Run Code Online (Sandbox Code Playgroud)

最后一行是这样的:

  1. 获取f对象.
  2. 是否f有其自己的财产被称为"答案"?
  3. 不,f有原型吗?
  4. 是的,原型是否有自己的属性叫做"回答"?
  5. 是的,返回该属性的值.

Object.create在问题的标题中提到过.重要的是要理解它Object.create与构造函数完全分开.它被添加到语言中,因此如果您不希望使用构造函数,则不必使用,但仍可以在创建该对象时直接设置对象的原型.


Ion*_*tan 6

那是因为它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' }
Run Code Online (Sandbox Code Playgroud)

但是,如果覆盖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 );  // {}
Run Code Online (Sandbox Code Playgroud)

这就是为什么你最好使用Object.getPrototypeOfES5中引入的新方法.

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' }
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是确保恢复constructor原型上的引用:

function Foo() {}

// Overwriting the initial prototype    
Foo.prototype = {
  constructor: Foo, // restore the constructor reference
  foo: "bar"
};
Run Code Online (Sandbox Code Playgroud)