Javascript原型行为

Tah*_*mad 5 javascript prototype delegation

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

Object.create = function(o) {
    var F = function() {};
    F.prototype=o;
    return new F();
}
Run Code Online (Sandbox Code Playgroud)

现在说,我有一个对象:

var car = {
   model: "Nissan"
};
Run Code Online (Sandbox Code Playgroud)

我使用"创建"方法基于此对象创建一个新对象:

var car1 = Object.create(car);
Run Code Online (Sandbox Code Playgroud)

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

car.year=2011;      // Gets added to "car"...
alert(car1.year);   // ... Is also avaialable to car1
Run Code Online (Sandbox Code Playgroud)

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

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

Object.prototype.originCountry = "Japan";
alert(car.originCountry);   // Outputs Japan
alert(car1.originCountry);  // Outputs Japan
Run Code Online (Sandbox Code Playgroud)

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

Object.carColor= "White";
alert(car.carColor);   // Error!
Run Code Online (Sandbox Code Playgroud)

Q2)当我向"car"添加属性时(参见上面的car.year示例,它会被添加到car的原型中.但是,当我向Object添加属性时,它不会被添加到Object的原型中吗?如果它被添加对于Object的原型,根据授权规则,为什么"car"无法使用它?

为什么会这样?

Roh*_*bhu 5

当你这样做:

Object.carColor = "White";
Run Code Online (Sandbox Code Playgroud)

然后该属性carColor不会被添加到Object原型中.它现在是一个属性Object.要了解您的期望,您要做的是:

Object.prototype.carColor = "White";
Run Code Online (Sandbox Code Playgroud)

之后:

alert(({}).carColor); // Will alert "White"
Run Code Online (Sandbox Code Playgroud)

那么这里发生的是.创建的任何对象{}(包括空对象)都是新实例,Object因此共享原型中设置的任何属性Object.

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

 1. var F = function() {};
Run Code Online (Sandbox Code Playgroud)

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

2. F.prototype=o;
Run Code Online (Sandbox Code Playgroud)

您将新空白函数的原型设置为您创建的对象.现在,这纯粹是一个参考.这不是一个深刻的副本.我的意思是,当对象o发生变化时,对象的任何实例也会发生变化(实际上它们不会发生变化,但它们似乎会"改变".稍后会有更多内容).

3. return new F();
Run Code Online (Sandbox Code Playgroud)

现在,您只需创建该函数的新实例,该实例将原型作为您传递的对象.

执行以下操作时:

var car1 = Object.create(car);
Run Code Online (Sandbox Code Playgroud)

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

car.year = 2011
Run Code Online (Sandbox Code Playgroud)

这不像car1变化.它更像是原型引用变化的对象.所以当你做的事情如下:

car1.year
Run Code Online (Sandbox Code Playgroud)

搜索(首先在原型中,然后在对象中)进行搜索year并调出一个属性,原型具有它,因此car1.year将返回2011.

所以底线是这样的:

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