5

我有一个方法可以让我在创建新对象时选择原型对象(复制自“Javascript:The Good Parts”一书):

Object.create = function(o) {
    var F = function() {};
    F.prototype=o;
    return new F();
}

现在说,我有一个对象:

var car = {
   model: "Nissan"
};

我基于这个对象创建了一个新对象,使用“创建”方法:

var car1 = Object.create(car);

然后我可以向 car 添加一个属性,它将动态添加到 car1(动态原型)。所以例如:

car.year=2011;      // Gets added to "car"...
alert(car1.year);   // ... Is also avaialable to car1

Q1)这种行为表明“年份”已添加到汽车的原型中,这就是它可用于 car1 的原因。它是否正确?如果没有,那么“年”在哪里添加,为什么“汽车”和“汽车1”都可以使用它?

此外,根据委托规则,如果在对象上找不到方法,它将搜索其原型,然后检查链上的所有原型,直到找到 Object.prototype。所以现在,如果我输入这样的内容:

Object.prototype.originCountry = "Japan";
alert(car.originCountry);   // Outputs Japan
alert(car1.originCountry);  // Outputs Japan

到现在为止还挺好; 但是,如果我这样做:

Object.carColor= "White";
alert(car.carColor);   // Error!

Q2)当我向“汽车”添加属性时(参见上面的car.year示例,它被添加到汽车的原型中。但是,当我向对象添加属性时,它不会被添加到对象的原型中?如果确实添加了到 Object 的原型,那么根据委托规则,为什么“汽车”不能使用它?

为什么会这样?

4

3 回答 3

5

当你这样做时:

Object.carColor = "White";

然后该属性carColor不会添加到Object的原型中。它现在是 的财产Object。要查看您的期望,您会做的是:

Object.prototype.carColor = "White";

然后在那之后:

alert(({}).carColor); // Will alert "White"

所以这里发生的事情就是这样。创建的任何对象{}(包括空对象)都是 的新实例,Object因此共享 . 原型中设置的任何内容的属性Object

至于你的Object.create功能是如何工作的。让我们逐行看一下:

 1. var F = function() {};

您只需创建一个新函数,一个本质上是空白的对象。您使用函数而不是类似函数的原因{}是因为函数可以与new调用相结合以创建该对象的新实例,其中该函数将充当构造函数。

2. F.prototype=o;

您将新空白函数的原型设置为您创建的对象。现在,这纯粹是一个参考。它不是深拷贝。我的意思是,随着对象的o变化,对象的任何实例也会发生变化(实际上它们不会改变,但它们会“似乎”改变。稍后会详细介绍)。

3. return new F();

现在您只需创建该函数的一个新实例,它有一个原型作为您传递的对象。

当您执行以下操作时:

var car1 = Object.create(car);

你得到一个car1具有原型的对象 has car。所以当你这样做时:

car.year = 2011

这不像car1变化。它更像是原型所指的对象发生了变化。因此,当您执行以下操作时:

car1.year

对一个被调用的属性进行搜索(首先在原型中,然后在对象中)year,结果证明原型拥有它,因此car1.year将返回2011

所以底线是这样的:

  1. 原型在实例之间共享。
  2. 更改 an 的属性Object不会体现在任何实例更改中。
于 2012-04-26T07:14:31.540 回答
1

在您的第一个示例中,您将添加到您的原型中,car1因为car === F.prototypecar1 instanceof F. 所以对 Q1:是的。

Object是所有对象的构造函数,F对你的car1. 如果你在 上添加一些东西Object.prototype,它将在所有对象上都可用——这就是你不应该这样做的原因,这种不可枚举的属性会弄乱所有的 for-in-loops。如果您设置Object构造函数的属性,则从它继承的内容不会发生任何变化。不要忘记:Object等于F函数,而不是o原型设置的参数。new Object()就像Object.create(Object.prototype)

于 2012-04-26T07:10:17.287 回答
0

该函数不允许您选择原型对象,它创建一个 nmew 对象构造函数,将对象参数作为原型,然后基于构造函数返回一个新对象。

该新对象将从对象参数继承方法和属性。这是为了允许创建从其他对象继承的新对象。

这样做的原因(顺便说一下 Object 是一个核心 javascript 对象,不应该被扩展)

Object.prototype.originCountry = "Japan";
alert(car.originCountry);   // Outputs Japan
alert(car1.originCountry);

而这并没有

Object.carColor= "White";

是因为首先扩展了Object的原型对象,这意味着使用Object构造函数构建的对象将继承那些方法和属性。

当后者是我们所说的静态函数时,它不会传递给从 Object 构造函数创建的对象。

我建议阅读更多关于 Javascript 中的原型继承的信息。这里有几个链接。

http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=xEJ2PwtH2Oh

http://unscriptable.com/2007/04/17/inheritance-explained/

于 2012-04-26T07:10:36.223 回答