10
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”的一个实例,为什么原型是未定义的?我的意思是,当我向“someObj”原型添加一个属性时,“p”可以访问它,那么为什么原型无法访问?

4

5 回答 5

11

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

关于

alert(p.prototype); // UNDEFINED, but why?

原因是该p对象没有称为“原型”的属性。它有一个底层原型,但这不是您访问它的方式。

所有函数对象都有一个名为的属性prototype,因此如果将它们用作构造函数,我们可以定义由这些构造函数创建的对象的底层原型的属性是什么。这可能会有所帮助:

function Foo() {
}
Foo.prototype.answer = 42;

console.log(Foo.prototype.answer); // "42"
var f = new Foo();
console.log(f.answer); // "42"

最后一行是这样工作的:

  1. 获取f对象。
  2. 是否f自己的属性称为“答案”?
  3. 不,f有原型吗?
  4. 是的,原型是否有自己的属性,称为“答案”?
  5. 是的,返回该属性的值。

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

于 2012-04-26T08:36:35.910 回答
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' }

但是,如果您覆盖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.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' }

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

function Foo() {}

// Overwriting the initial prototype    
Foo.prototype = {
  constructor: Foo, // restore the constructor reference
  foo: "bar"
};
于 2012-04-26T08:44:36.350 回答
2

p.prototype 不起作用,因为在这种情况下 p = someObj.prototype。

基本上,当您使用 new 运算符时,会发生构造函数 someObj 用于初始化新对象的情况。这意味着它返回一个具有构造函数原型的属性和方法的对象。

因此 p = someObj.prototype 和 p.prototype 是未定义的,因为 p 不是构造函数。

这篇文章可能有助于解释这一点

http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=A2ikc3JLxeD

于 2012-04-26T08:37:38.633 回答
1

p是 的一个实例someObj原型属于构造函数。您可以使用检索p的构造函数原型p.constructor.prototype

于 2012-04-26T08:37:59.840 回答
0

在 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 的原因。

于 2012-04-26T08:47:39.827 回答