object.create如何在JavaScript中工作?

Bri*_*ian 19 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
Run Code Online (Sandbox Code Playgroud)

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

我也可以用Object.create:

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

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

CMS*_*CMS 35

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

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

你的两个片段之间的区别在于,__proto__你正在改变原型food.在第二个示例中,您只是分配一个继承自的新对象more_food,这food.fruit就是解决原因的原因undefined,因为您的原始food对象会被该赋值丢失.

Object.create究竟在做什么?

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

变量食物是否分配了对原型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"
Run Code Online (Sandbox Code Playgroud)

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

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

那么,more_food.fruit是一个继承的属性:

more_food.hasOwnProperty('fruit'); // false, inherited
'fruit' in more_food;              // true
Run Code Online (Sandbox Code Playgroud)

虽然vegetable自己的财产more_food:

more_food.hasOwnProperty('vegetable'); // true
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

请记住,这__proto__是一个非标准功能,它将在未来从实现中删除,已经在Mozilla文档中被列为已弃用,这是其主要原因,这也是该语言可能永远不会有办法的原因以这种方式改变原型链允许您在VM和JIT级别上导致优化和安全问题.__proto__

  • 谢谢,很好的解释!现在我理解这是一个简单的概念. (3认同)
  • @Brian,不客气!我很乐意帮忙! (2认同)
  • 很好的解释 (2认同)