我有一个方法可以让我在创建新对象时选择原型对象(从“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”?
为什么会这样?
答案 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
所以底线是:
Object
的属性不会显示在任何更改的实例中。答案 1 :(得分:1)
在您的第一个示例中,您要添加car1
的原型,因为car === F.prototype
和car1 instanceof F
。所以Q1:是的。
Object
是所有对象的构造函数,因为F
是car1
。如果你在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