对象包含相同的值,但不应该
我尝试实现对象继承,其中每个对象共享相同的功能,但包含不同的值/容器。这样做时,我发现了一种奇怪的行为;每个单独的对象都像符咒一样工作,但它们都有相同的选项。请务必澄清我的意思,我添加了示例代码。
我要做的是从每个元素读取数据值,并将其绑定到选项。某些函数需要这些才能正常工作!
<div class="first" data-value="first div"></div>
<div class="second" data-value="second div"></div>
<script>
var original = {
options: {
value: null,
factor: 13
},
init: function (container) {
this.options.value = container.getAttribute('data-value');
}
};
var variation = Object.create(original);
variation.options.factor = 37;
var firstDiv = Object.create(variation);
var secondDiv = Object.create(variation);
firstDiv.init(document.getElementsByTagName('div')[0]);
secondDiv.init(document.getElementsByTagName('div')[1]);
alert('firstDiv.options === secondDiv.options: ' + (firstDiv.options === secondDiv.options)); // but should be false!
</script>
请注意,这只显示了实际对象的一小部分。在我看来,所有其他部分都是无关紧要的。
我希望问题出在哪里。另外,我是故意使用Object.create()
的。
解决方案
对象包含相同的值,但不应该
应该如此,因为您没有更改variation
上的options
属性,所以它仍然指向original.options
指向的同一对象。
执行此操作时:
var original = {
options: {
value: null,
factor: 13
},
init: function (container) {
this.options.value = container.getAttribute('data-value');
}
};
以下是您在内存中获得的内容(省略了一些细节):
+−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−+ +−−−>| (Object.prototype) |<−+ original−−−>| (object) | | +−−−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−+ | | | __proto__ |−−−+ +−−−−−−−−−−−−−+ | | options |−−−−−−−>| (object) | | | init |−−−+ +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−+ | | __proto__ |−−−−−−−−−+ | | value: null | | | factor: 13 | | +−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−+ +−−−−| (function) | +−−−−−−−−−−−−+
.其中__proto__
是显示对象原型的伪属性(具体地说,规范称为对象的内部[[Proto]]
属性的值)。(在浏览器ES2015中,实际上有一个__proto__
访问器,但不应该使用它。)
执行此操作时:
var variation = Object.create(original);
您拥有:
+−−−−−−−−−−−−+ variation−−>| (object) | +−−−−−−−−−−−−+ | __proto__ |−−+ +−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−−−−−−+ | +−>| (Object.prototype) |<−+ +−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−−−−+ | original−−−>| (object) | | | +−−−−−−−−−−−−+ | | | __proto__ |−−−−−+ +−−−−−−−−−−−−−+ | | options |−−−−−−−>| (object) | | | init |−−−+ +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−+ | | __proto__ |−−−−−−−−−+ | | value: null | | | factor: 13 | | +−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−+ +−−−−| (function) | +−−−−−−−−−−−−+
您可以看到original
和variation
仍然指向相同的选项对象。
如果您想要单独的选项对象,则必须创建一个新对象。您可以使variation.options
使用original.options
作为其原型:
var variation = Object.create(original);
variation.options = Object.create(original.options);
.但之后您必须为firstDiv
和secondDiv
重新:
var firstDiv = Object.create(variation);
firstDiv.options = Object.create(variation.options);
var secondDiv = Object.create(variation);
secondDiv.options = Object.create(variation.options);
.这表明我们需要做一些不同的事情。
您可以使用一个函数来执行此操作:
function createVariation(source) {
var v = Object.create(source);
v.options = Object.create(source.options);
return v;
}
var variation = createVariation(original);
var firstDiv = createVariation(variation);
var secondDiv = createVariation(variation);
.但您可能会看到构造函数或生成器函数,以及一个相当典型的模式,称为扩展函数(如jQuery's或Underscore's)。
相关文章