Javascript原型行为

时间:2012-04-26 06:56:34

标签: javascript prototype delegation

我有一个方法可以让我在创建新对象时选择原型对象(从“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);

然后我可以向汽车添加一个属性,它将动态地添加到car1(动态原型设计)。所以对于例如:

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

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

另外,根据委托规则,如果在对象上找不到方法,它将搜索其原型,然后检查链中的所有原型,直到它到达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”添加属性时(参见上面的 car.year 示例,它会被添加到car的原型中。但是,当我向Object添加属性时,它没有被添加到Object的原型中?如果它被添加到Object的原型中,那么根据委托规则,为什么它不能用于“car”?

为什么会这样?

3 个答案:

答案 0 :(得分: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的对象car。所以当你这样做时:

car.year = 2011

car1更改不同。它更像是原型引用变化的对象。所以,当你做类似的事情时:

car1.year

对名为year的属性进行搜索(首先在原型中,然后在对象中),结果是原型具有它,因此car1.year将返回2011

所以底线是:

  1. 原型在实例之间共享。
  2. 更改Object的属性不会显示在任何更改的实例中。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

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

这是有效的原因(以及对象是核心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/