KolyaniuS
@KolyaniuS
безнадежный оптимист

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

Как известно переменная, которой присвоено значение в виде объекта или массива, на самом деле хранит только ссылку в область памяти, в которой храниться этот массив или объект.
Так же известно, что метод slice() для значения представленного в виде массива копирует часть этого массива (либо весь) в другую переменную, при этом переменные будут указывать на две разные области в памяти, т.е.
a = [1,2,3];
b = a.slice();
b[0] = 2;
alert(a); // [1,2,3]
alert(b); // [2,2,3]

Но стоит поместить в массив элементы, представляющие собой объекты, как такой способ перестает работать.
Пример:
a = [{x:1,y:1}];
b = a.slice();
b[0].x = 2;
alert(a); // [{x:2,y:1}]
alert(b); // [{x:2,y:1}]

Вопросы:
1. Почему так происходит?
2. Как в таком случае создать новую копию целевого массива, элементы которого представляют собой объекты?
Пробовал через цикл, таким образом:
var arr = [ {x:1, y:1} ];
var new_arr = [];
var new_arr_elem = {};

for (var i=0; i<arr.length; i++) {
  arr_elem = arr[i];
  for (var key in arr_elem) {
    new_arr_elem = arr_elem[key];
  }
  new_arr.push(new_arr_elem);
}

Не могу сообразить почему это не работает (точнее работает не так как я это себе представляю) - натолкните на правильную мысль.
  • Вопрос задан
  • 8995 просмотров
Решения вопроса 1
KolyaniuS
@KolyaniuS Автор вопроса
безнадежный оптимист
Всем спасибо за советы - сделал так:

var arr = [{x: 1, y: 1}, {x: 2, y: 2}];
var new_arr = cloneArray(arr);

new_arr[0].x = 2;
new_arr[1].x = 5;

console.log(arr);
console.log(new_arr);

function cloneArray(arr) {
  var result = [];
  arr.forEach(function(value) {
    var arr_elem = {};
    for (var prop in value) 
      arr_elem[prop] = value[prop];
    result.push(arr_elem);
  });
  return result;
}


Поскольку задача достаточно узкоспециализированная и мой опыт в JS оставляет желать лучшего - такой вариант вполне удовлетворяет.
Если будут идеи по-интереснее - пишите :)
ЗЫ: только без регулярок и парсинга )
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@serega_kaktus
Программист-самоучка, фрилансер
1. Почему так происходит?

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

например, тут пишут, как клонировать объект. Думаю, сможете применить к циклу
Ответ написан
miraage
@miraage
Старый прогер
Объект копируются по ссылке, а не по значению.
Попробуйте так (DEMO):

var a = [{x: 1, y: 1}, {x: 2, y: 2}];
var b = cloneArray(a);

b[0].x = 5;

console.log(a);
console.log(b);

function cloneArray(arr) {
  var result = [];
  
  arr.forEach(function(value) {
    if (!isPrimitive(value)) {
      value = copy(value);
    }
    
    result.push(value);
  });
  
  return result;
}

function isPrimitive(value) {
  // string, boolean, number
  return value == null || /^[sbn]/.test(typeof value);
}

// корректно работает только для простых объектов
function copy(value) {
  return JSON.parse(JSON.stringify(value));
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы