object.create如何在JavaScript中工作?

时间:2011-11-01 05:44:22

标签: javascript inheritance prototype-programming object-create

告诉我,如果我错了:

原型是普通对象。当一个对象继承原型时,它不仅仅复制原型的属性,该对象存储对原型的引用。

在Firefox中,我可以这样做:

var food = {fruit:"apple"};
var more_food = {vegetable:"celery"};
food.__proto__ = more_food;
food.vegetable // celery
food.fruit // apple

我可以使用__proto__属性手动设置对原型对象的引用。

我也可以使用Object.create

var food = {fruit:"apple"};
var more_food = {vegetable:"celery"};
food = Object.create(more_food);
food.vegetable // celery
food.fruit // undefined

Object.create到底在做什么?变量食物是否分配了对原型more_food的引用,或者是Object.create只返回对象的副本more_food?如果Object.create只是制作副本,那么如果变量食物没有引用more_food,原型链如何工作?

1 个答案:

答案 0 :(得分:35)

  

原型是普通对象。当一个对象继承原型时,它不仅仅复制原型的属性,该对象存储对原型的引用。

你是对的,一个对象的原型,只是通过原型链引用的另一个对象。

您的两个片段之间的区别在于,__proto__变异 food的原型。在第二个示例中,您只是分配一个继承自more_food的新对象,这就是food.fruit被解析为undefined的原因,因为您的原始food对象是失去了这项任务

  

Object.create到底在做什么?

Object.create构建一个新对象,它继承自作为第一个参数传递的对象(它只能是一个对象或null)。

  

变量food是否分配了对原型more_food的引用,或者是Object.create只是返回了对象的副本more_food?

您的food变量将保留一个新对象,该对象继承自more_food,此操作中没有任何复制。

例如:

var food = {fruit:"apple"};
var more_food = Object.create(food, {
  vegetable: { value: "celery" }
});

more_food.fruit;     // "apple"
more_food.vegetable; // "celery"

在上面的示例中,more_food继承自food,换句话说,foodmore_food的原型,此原型参考存储在名为的内部属性中[[Prototype]]Object.create的第二个参数允许您初始化此新对象的属性。

没有复制,上面的例子more_food.fruit只是简单的委托可通过原型链访问,属性查找过程非常简单,如果找不到属性对象,它在对象的原型上以递归的方式再次查找(委托!),直到找到原型为null的对象(如Object.prototype)。

因此,more_food.fruit是一个继承的属性:

more_food.hasOwnProperty('fruit'); // false, inherited
'fruit' in more_food;              // true

虽然vegetablemore_food自有属性,但

more_food.hasOwnProperty('vegetable'); // true

上面的例子看起来像这样:


  +---------------------+  [[Prototype]]  +---------------+
  | more_food           |+--------------->| food          |
  |---------------------|                 |---------------|
  | vegetable: "celery" |                 | fruit: "apple |
  +---------------------+                 +---------------+
  

如果Object.create只是制作副本,那么如果变量食物没有引用more_food,原型链如何工作?

Object.create不会创建对象的副本,它只是在创建新对象时设置原型。

请注意,__proto__非标准功能,将来会从实施中删除,已被列为已弃用Mozilla Documentation上,这是主要原因,这也是为什么语言可能永远无法以__proto__允许的方式改变原型链的原因,因为它会导致优化和安全问题, VM和JIT的级别。