对象创建时的Javascript选择性继承

时间:2017-03-10 10:55:25

标签: javascript prototypal-inheritance

假设我有类似的对象关系;

{{1}}

在上面的代码中,当我创建了第三个对象时,它还将继承预期的firstObject属性。我想知道的是,有没有优雅(我的意思是没有 使用hasOwnProperty属性迭代secondObject属性的方法 在创建thirdObject时只继承secondObject属性?

1 个答案:

答案 0 :(得分:3)

  

有没有优雅(我的意思是没有使用hasOwnProperty属性迭代secondObject属性)在创建thirdObject时只继承secondObject属性的方法?

不,事实上,也没有(合理的)不优雅的方式去做;从thirdObject生成secondObject 继承意味着它将继承所有secondObject的属性以及其原型中的属性。

如果您希望thirdObject不拥有firstObject的属性,则thirdObject不应该(间接)从firstObject继承。

你有三个选择("不合理"第四个以后):

复制属性

您可以使用Object.assign secondObject自己的属性复制到thirdObject

var thirdObject = Object.assign({}, secondObject);

...但它不会是继承,只是一个快照。但这可能是最好的。 (Object.assign已添加到ES2015 [aka" ES6"]中,但可以为旧的JavaScript引擎进行填充。)

使用getter / setter模拟继承

或者,这确实需要迭代secondObject自己的属性,您可以为getter和setter提供thirdObject匹配属性:



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;
}




在那里,我们模仿继承,让thirdObjectsecondObject获取值,直到/除非有东西给它赋值,在这种情况下我们将它作为标准数据属性。

使用带有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;
}




* 不合理的方式是使用Proxy(ES2015 +,而非polyfillable):



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.
&#13;
&#13;
&#13;

... 但是我无法想象您在继承链中想要一个代理对象,尤其是因为它会对性能产生影响。 :-)所以我不会这样做。 (而且我确定上面的例子不完整。)