通过Object.create()的Javascript原型

时间:2012-04-26 08:33:31

标签: 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?

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

5 个答案:

答案 0 :(得分:11)

这里重要的是函数对象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"

最后一行是这样的:

  1. 获取f对象。
  2. f是否具有名为“answer”的拥有属性?
  3. 不,f有原型吗?
  4. 是的,原型是否具有名为“answer”的拥有属性?
  5. 是,返回该属性的值。
  6. 您在问题标题中提到了Object.create。重要的是要理解Object.create与构造函数完全分开。它被添加到语言中,因此如果您不想使用构造函数,则不必,但仍然可以设置对象的原型 - 直接创建该对象时。

答案 1 :(得分: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 );  // {}

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

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"
};

答案 2 :(得分: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

答案 3 :(得分:1)

psomeObj实例。原型属于构造函数。您可以使用p

检索p.constructor.prototype的构造函数原型

答案 4 :(得分:0)

在Javascript,构造函数中,实际上所有函数都获得了一个prototype属性。对象(即一组键值对)没有prototype属性。在上面的示例中,

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不是。