原型是一个普通的对象。当一个对象继承一个原型时,它不只是复制原型的属性,对象存储了对原型的引用。
没错,一个对象的原型,只是通过原型链引用的另一个对象。
你的两个片段之间的区别在于__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
,换句话说,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
Whilevegetable
是 的自有财产:more_food
more_food.hasOwnProperty('vegetable'); // true
上面的示例在图形上看起来像这样:
+----------+ [[原型]] +---------------+
| more_food |+--------------->| 食品|
|----------------------| |---------------|
| 蔬菜:“芹菜” | | 水果:“苹果 |
+----------+ +--------------+
如果 Object.create 只是制作一个副本,那么如果变量 food 没有引用 more_food,那么原型链是如何工作的呢?
Object.create
不创建对象的副本,它只是在创建新对象时设置其原型。
请记住,这__proto__
是一个非标准功能,将来会从实现中删除,在Mozilla 文档中已被列为已弃用,这是主要原因,这也是该语言可能永远无法使用的原因以允许你的方式改变原型链是它会导致优化和安全问题,在 VM 和 JIT 级别。__proto__