对象包含相同的值但不应该

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()故意使用的.

T.J*_*der 5

对象包含相同的值但不应该

他们应该,因为你没有改变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) |
                                  +------------+

您可以看到两者originalvariation仍然指向相同的选项对象.

如果需要单独的选项对象,则必须创建新对象.你可以让variation.options使用original.options它的原型:

var variation = Object.create(original);
variation.options = Object.create(original.options);
Run Code Online (Sandbox Code Playgroud)

...但你必须做它再次firstDivsecondDiv:

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)

...但你可能会看一下构造函数或制造商函数,以及一个称为"扩展"函数的相当典型的模式(例如jQueryUnderscore).

  • 您的ASCII图表技巧令人印象深刻.:) (2认同)