假设我有这样的对象关系;
var firstObject = { prop1:"prop1", prop2:"prop2" };
var secondObject = Object.create(firstObject);
secondObject.prop3 = "prop3";
secondObject.prop4 = "prop4";
var thirdObject = Object.create(secondObject);
在上面的代码中,当我创建thirdObject时,它也会继承预期的firstObject属性。我想知道的是,有没有优雅的(我的意思是没有 使用 hasOwnProperty 属性迭代 secondaryObject 属性)的方法 创建 ThirdObject 时仅继承 SecondObject 属性?
最佳答案
are there any elegant (I mean without iterating over secondObject properties with hasOwnProperty property) ways to inherit just secondObject properties while creating thirdObject?
不,事实上,也没有(合理*)不优雅的方法来做到这一点;让 thirdObject
继承 from secondObject
意味着它将继承 secondObject
的所有属性及其原型(prototype)中的属性( s)。
如果您希望 thirdObject
不具有 firstObject
的属性,则 thirdObject
不应从 firstObject< 继承(间接)/
.
给你的三个选择(以及后面的“不合理”的第四个选择):
复制属性
您可以使用Object.assign
将secondObject
自己的属性复制到thirdObject
:
var thirdObject = Object.assign({}, secondObject);
...但它不是继承,只是一个快照。但这可能是最好的。 (Object.assign
是在 ES2015 [又名“ES6”] 中添加的,但可以为较旧的 JavaScript 引擎进行填充。)
使用 getter/setter 模拟继承
或者,这确实需要迭代 secondObject
自己的属性,您可以为 thirdObject
提供具有 getter 和 setter 的匹配属性:
var firstObject = { prop1:"prop1", prop2:"prop2" };
var secondObject = Object.create(firstObject);
secondObject.prop3 = "prop3";
secondObject.prop4 = "prop4";
var thirdObject = {};
Object.keys(secondObject).forEach(function(key) {
Object.defineProperty(thirdObject, key, {
get: function() {
return secondObject[key];
},
set: function(value) {
delete this[key]; // Release the getter/setter for this
this[key] = value; // ...and make it an own property
},
configurable: true,
enumerable: true
});
});
console.log("prop1" in firstObject); // true
console.log("prop1" in secondObject); // true
console.log("prop1" in thirdObject); // false
console.log("--");
console.log("prop3" in firstObject); // false
console.log("prop3" in secondObject); // true
console.log("prop3" in thirdObject); // true
console.log("--");
console.log(firstObject.prop1); // prop1
console.log(secondObject.prop1); // prop1
console.log(thirdObject.prop1); // undefined
console.log("--");
console.log(firstObject.prop3); // undefined
console.log(secondObject.prop3); // prop3
console.log(thirdObject.prop3); // prop3
.as-console-wrapper {
max-height: 100% !important;
}
在那里,我们通过让 thirdObject
从 secondObject
获取值来模拟继承,直到/除非有东西给它赋值,在这种情况下,我们将其设为标准数据属性.
通过带有 getter 的中介使用继承
或者你可以让thirdObject
从一个遵循secondObject
自己的属性的中介继承(更简单一点,然后“自己的”标志是正确的) :
var firstObject = { prop1:"prop1", prop2:"prop2" };
var secondObject = Object.create(firstObject);
secondObject.prop3 = "prop3";
secondObject.prop4 = "prop4";
var thirdProto = {};
Object.keys(secondObject).forEach(function(key) {
Object.defineProperty(thirdProto, key, {
get: function() {
return secondObject[key];
},
configurable: true,
enumerable: true
});
});
var thirdObject = Object.create(thirdProto);
console.log("prop1" in firstObject); // true
console.log("prop1" in secondObject); // true
console.log("prop1" in thirdObject); // false
console.log("--");
console.log("prop3" in firstObject); // false
console.log("prop3" in secondObject); // true
console.log("prop3" in thirdObject); // true
console.log("--");
console.log(firstObject.prop1); // prop1
console.log(secondObject.prop1); // prop1
console.log(thirdObject.prop1); // undefined
console.log("--");
console.log(firstObject.prop3); // undefined
console.log(secondObject.prop3); // prop3
console.log(thirdObject.prop3); // prop3
.as-console-wrapper {
max-height: 100% !important;
}
* 不合理的方法是使用代理
(ES2015+,不可填充):
var firstObject = { prop1:"prop1", prop2:"prop2" };
var secondObject = Object.create(firstObject);
secondObject.prop3 = "prop3";
secondObject.prop4 = "prop4";
var thirdObject = Object.create(new Proxy(secondObject, {
has: function(target, prop) {
return target.hasOwnProperty(prop) || secondObject.hasOwnProperty(prop);
},
get: function(target, prop) {
return target.hasOwnProperty(prop) || secondObject.hasOwnProperty(prop) ? target[prop] : undefined;
},
set: function(target, prop, value) {
target[prop] = value;
return true;
}
}));
console.log("prop1" in firstObject); // true
console.log("prop1" in secondObject); // true
console.log("prop1" in thirdObject); // false
console.log("--");
console.log("prop3" in firstObject); // false
console.log("prop3" in secondObject); // true
console.log("prop3" in thirdObject); // true
console.log("--");
console.log(firstObject.prop1); // prop1
console.log(secondObject.prop1); // prop1
console.log(thirdObject.prop1); // undefined
console.log("--");
console.log(firstObject.prop3); // undefined
console.log(secondObject.prop3); // prop3
console.log(thirdObject.prop3); // prop3
.as-console-wrapper {
max-height: 100% !important;
}
Note: Requires a browser with <code>Proxy</code> support.
...但是我无法想象您想要在继承链中使用代理对象,尤其是因为它会对性能产生影响。 :-) 所以我不会这样做。 (我确信上面的例子是不完整的。)
关于Javascript 在对象创建时选择性继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42716659/