php*_*oob 3 javascript javascript-objects
我尝试实现一个对象继承,其中每个对象共享相同的功能,但包含不同的值/容器.这样做我发现了一种奇怪的行为; 每个单独的对象都像魅力一样,但它们都有相同的选择.请澄清我的意思,我添加了一个示例代码.
我想要做的是从每个元素读取数据值并将其绑定到选项.在某些功能中需要这些才能正常工作!
<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>
Run Code Online (Sandbox Code Playgroud)
请注意,这只是显示实际对象的一小部分.在我看来,所有其他部分都是无关紧要的.
我希望问题很清楚.我也是Object.create()故意使用的.
对象包含相同的值但不应该
他们应该,因为你没有改变options属性variation,所以它仍然指向指向同一个对象original.options.
当你这样做:
var original = {
options: {
value: null,
factor: 13
},
init: function (container) {
this.options.value = container.getAttribute('data-value');
}
};
Run Code Online (Sandbox Code Playgroud)
这是你在内存中得到的(省略了一些细节):
+--------------------+
+------------+ +--->| (Object.prototype) |<-+
original--->| (object) | | +--------------------+ |
+------------+ | |
| __proto__ |---+ +-------------+ |
| options |------->| (object) | |
| init |---+ +-------------+ |
+------------+ | | __proto__ |---------+
| | value: null |
| | factor: 13 |
| +-------------+
|
| +------------+
+----| (function) |
+------------+
...其中__proto__是一个伪属性,显示对象的原型是什么(具体来说,是spec调用对象内部[[Proto]]属性的值).(在浏览器中,在ES2015中,实际上有一个__proto__访问器,但不应该使用它.)
然后当你这样做:
var variation = Object.create(original);
Run Code Online (Sandbox Code Playgroud)
你有:
+------------+
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);
Run Code Online (Sandbox Code Playgroud)
...但你必须做它再次为firstDiv和secondDiv:
var firstDiv = Object.create(variation);
firstDiv.options = Object.create(variation.options);
var secondDiv = Object.create(variation);
secondDiv.options = Object.create(variation.options);
Run Code Online (Sandbox Code Playgroud)
......这表明我们需要做一些与众不同的事情.
您可以使用一个功能来执行此操作:
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);
Run Code Online (Sandbox Code Playgroud)
...但你可能会看一下构造函数或制造商函数,以及一个称为"扩展"函数的相当典型的模式(例如jQuery或Underscore).