为什么变量的副本会被意外更改?

时间:2016-06-14 16:44:15

标签: javascript

我创建了变量bpJson,并不理解它为什么会发生变化。我是控制台每5秒记录一次,它会改变每次迭代。我只期望babyPieData改变,而bpJson每次都保持不变。 setPieOptions中没有bpJson,所以我没有包含该函数的代码。

var createVariance = function(bpJson, babyPieData){
    var n = bpJson.length;
    for ( var i = 0; i < n; i++){
        var amount = Math.floor(Math.random() * 4);
        var operator = Math.floor(Math.random() *2) + 1;
        if (operator === 1){
            babyPieData[i] = (bpJson[i] + amount);
            if (babyPieData[i] > 100){
                babyPieData[i] = 100;
            }
        }else{
            babyPieData[i] = (bpJson[i] - amount);
            if (babyPieData[i] < 0){
                babyPieData[i] = 1;
            }
        }
        setPieOptions(babyPieData);
    }
};

var getBabyPieData = function(){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'php/baby-pie.php');
    xhr.send();
    xhr.onload = function(){
        var babyPieData = JSON.parse(xhr.response);
        console.log('original babyPieData = ' + babyPieData);
        var bpJson = babyPieData;
        setPieOptions(babyPieData);
        var babyPieDataTimer = window.setInterval(function(){
            createVariance(bpJson, babyPieData);
            console.log(bpJson);
        }, 5000);
    };
}();

3 个答案:

答案 0 :(得分:4)

从您的代码中可以清楚地看到您正在使用一个对象;看起来它可能是一个数组。

变量不直接包含数组之类的对象,它们包含引用;实际的对象是别处。您可以将其描述为具有数字的变量,该变量告诉JavaScript引擎在哪里找到对象:

+-------------+             
| babyPieData |             
+-------------+             +---------+
| Ref:123456  |------------>| (Array) |
+-------------+             +---------+
                            | 0: 42   |
                            | 1: 67   |
                            +---------+

所以问题是这一行不符合你的想法:

var bpJson = babyPieData;

这不会创建数组的副本。它只是为数组创建引用的第二个副本。两个变量仍然引用(指向)相同的数组:

+-------------+       
| babyPieData |       
+-------------+       
| Ref:123456  |------+
+-------------+      |
                     |
                     |      +---------+
                     +----->| (Array) |
+-------------+      |      +---------+
| bpjSon      |      |      | 0: 42   |
+-------------+      |      | 1: 67   |
| Ref:123456  |------+      +---------+
+-------------+             

如果要复制数组,则需要有意识地执行此操作。如果数组包含简单值(如图所示),您可以这样做:

var bpJson = babyPieData.slice();
没有参数的

slice会创建一个浅表副本:

+-------------+             
| babyPieData |             
+-------------+             +---------+
| Ref:123456  |------------>| (Array) |
+-------------+             +---------+
                            | 0: 42   |
                            | 1: 67   |
                            +---------+
+-------------+             
| bpJson      |             
+-------------+             +---------+
| Ref:554654  |------------>| (Array) |
+-------------+             +---------+
                            | 0: 42   |
                            | 1: 67   |
                            +---------+

答案 1 :(得分:3)

因为bpJsonbabyPieData是同一个对象。

答案 2 :(得分:-1)

"How to clone a js object elegantly"

正如@Scott&#34所说;因为bpJson和babyPieData是同一个对象。&#34; 按照链接创建任何js对象的独立副本,而不是特定的数组。