2015-11-26 2 views
2

При попытке изменить текущий элемент во время итерации по массиву сбой модификации. Ниже приведен пример кода.Модификация массива в то время как итерация

var s_arr = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}]; 
var arr = []; 

for(var i in s_arr) { 

    if(s_arr[i].a == 5) { 

    s_arr[i].b = 0; 
    console.log('First modification: ' +JSON.stringify(s_arr[i])); 
    arr.push(s_arr[i]); 

    s_arr[i].b = 9; 
    console.log('Second modification: ' +JSON.stringify(s_arr[i])); 
    arr.push(s_arr[i]); 
    } 

} 

console.log('Final: ' +JSON.stringify(arr)); 

После запуска выше сценарий node test.js, ниже результат.

First modification: {"a":5,"b":0} 
Second modification: {"a":5,"b":9} 
Final: [{"a":5,"b":9},{"a":5,"b":9}] 

Ожидаемый результат:

First modification: {"a":5,"b":0} 
Second modification: {"a":5,"b":9} 
Final: [{"a":5,"b":0},{"a":5,"b":9}] 

Однако при добавлении нового объекта во время итерации & присвоения каждому значения текущего элемента (объекта) интенсивно работает.

var s_arr = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}]; 
var arr = []; 

for(var i in s_arr) { 

    if(s_arr[i].a == 5) { 

    s_arr[i].b = 9; 
    console.log('Second modification: ' +JSON.stringify(s_arr[i])); 
    arr.push(s_arr[i]); 

    var a = {}; 
    a.a = s_arr[i].a; 
    a.b = 0; 
    arr.push(a); 

    var b = {}; 
    b.a = s_arr[i].a; 
    b.b = 9; 
    arr.push(b); 
    } 

} 

console.log('Final: ' +JSON.stringify(arr)); 

Ниже приводится результат изменения сценария.

Final: [{"a":5,"b":0},{"a":5,"b":9}] 

Почему первый скрипт при запуске показывает модификацию объекта справа, но окончательный массив показывает, что состоит из измененных объектов, не так, как ожидалось?

+0

возможно, потому что это тот же объект? .. он не нажимает копию этого объекта в массиве, поэтому вы добавляете ту же ссылку на объект дважды. – Hacketo

+0

Объекты, всегда передаваемые по ссылке, вы должны клонировать вручную –

ответ

2

Объекты, которые всегда передавались по ссылке в JS.

arr.push(s_arr[i]); не создает копию объекта, он просто сохраняет ссылку на него в массиве arr;
Так что любые изменения внутри объекта вы увидите в массиве тоже.

Вы должны явно клонировать свой объект, чтобы предотвратить изменения.
Например, вы можете использовать serialize-deserialize пару:

arr.push(JSON.parse(JSON.stringify(s_arr[i]))); 

Ваш

var a = {}; 
a.a = s_arr[i].a; 
a.b = 0; 
arr.push(a); 

будет работать тоже, потому что вы создаете новый экземпляр объекта здесь и использовать только скалярные свойства, чтобы заполнить его.

Смежные вопросы