我一直在阅读道格拉斯·克罗克福德(DouglasCrockford)撰写的“Javascript:好的部分”,尽管有些极端,但我同意他的许多意见。
在第3章中,他讨论了对象,并在某一时刻列出了一种模式,以简化和避免使用内置的“ new”关键字带来的一些混淆/问题。
if (typeof Object.create !== 'function') { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } newObject = Object.create(oldObject);
因此,我尝试在正在处理的项目中使用它,并且在尝试从嵌套对象继承时发现了一个问题。如果我覆盖使用此模式继承的嵌套对象的值,则它将覆盖原型链中的嵌套元素。
Crockford的示例类似于flatObj下面的示例,效果很好。但是,该行为与嵌套对象不一致:
flatObj
var flatObj = { firstname: "John", lastname: "Doe", age: 23 } var person1 = Object.create(flatObj); var nestObj = { sex: "female", info: { firstname: "Jane", lastname: "Dough", age: 32 } } var person2 = Object.create(nestObj); var nestObj2 = { sex: "male", info: { firstname: "Arnold", lastname: "Schwarzenneger", age: 61 } } var person3 = { sex: "male" } person3.info = Object.create(nestObj2.info); // now change the objects: person1.age = 69; person2.info.age = 96; person3.info.age = 0; // prototypes should not have changed: flatObj.age // 23 nestObj.info.age // 96 ??? nestObj2.info.age // 61 // now delete properties: delete person1.age; delete person2.info.age; delete person3.info.age; // prototypes should not have changed: flatObj.age // 23 nestObj.info.age // undefined ??? nestObj2.info.age // 61
我是在做错什么,还是这是这种模式的局限性?
没有矛盾。只是不要考虑嵌套对象:对象的直接属性总是在其原型上或在自己的属性上。属性值是否为基元或对象与无关紧要。
所以,当你这样做
var parent = { x: {a:0} }; var child = Object.create(parent);
child.x将引用与parent.x-一个{a:0}对象相同的对象。当您更改其属性时:
child.x
parent.x
{a:0}
var prop_val = child.x; // == parent.x prop_val.a = 1;
两者都会受到影响。要独立更改“嵌套”属性,您首先必须创建一个独立的对象:
child.x = {a:0}; child.x.a = 1; parent.x.a; // still 0
你能做的是
child.x = Object.create(parent.x); child.x.a = 1; delete child.x.a; // (child.x).a == 0, because child.x inherits from parent.x delete child.x; // (child).x.a == 0, because child inherits from parent
which means they are not absolutely independent - but still two different objects.