Я сталкиваюсь с чем-то, что я не понимаю с массивом. Действительно, я создал массив, который я заполнил пустыми подмассивами, чтобы получить 2D матрицу. Но когда я манипулирую массивом, он не ведет себя так, как я ожидал.
var arr = new Array(5);
arr.fill([]);
arr[2].push("third rank item");
console.log(arr);
//[ [ 'third rank item' ],
// [ 'third rank item' ],
// [ 'third rank item' ],
// [ 'third rank item' ],
// [ 'third rank item' ] ]
Каждый свет по этому вопросу будет приветствоваться
7 ответов
Это та же самая старая проблема с массивами (и объектами в целом), являющимися ссылками, а не значениями.
В частности, когда вы делаете arr.fill([])
, вы берете этот единственный пустой массив и используете его для заполнения родительского.
Это как сказать:
var arr = new Array(5);
arr[0] = arr[1] = arr[2] = arr[3] = arr[4] = [];
Все они ссылаются на один и тот же массив! Поэтому, когда вы затем продолжаете модифицировать один из них, похоже, что они все модифицированы (но на самом деле это все тот же)
К сожалению, нет простого способа присвоить пустой массив каждому. Вы могли бы сделать что-то вроде:
Array.apply(null, Array(5)).map(function() {return [];});
По сути, создайте (инициализированный) пустой массив длиной 5 и сопоставьте каждое (пустое) значение с новым []
.
РЕДАКТИРОВАТЬ: Кажется, я застрял в старые времена. Согласно комментарию @ torazaburo, вы можете использовать Array.from
вместо Array.apply(null, Array(5)).map
, например так:
Array.from( new Array(5), function() { return []; } );
В ES6 я рекомендую этот метод для создания 2-х или многомерных массивов:
// create an M x N dimension grid and fill it with 0's
const myArray = [...Array(M)].map(r => [...Array(N)].map(r => 0));
Как вы можете заметить, используя array.fill, вы заполняете массив ссылкой на тот же массив,
Если вы хотите создать экземпляр каждого индекса массива в пустом массиве, то обычный цикл while сделает:
var arr = [];
var n = 5
while(n--)
arr[n] = []
arr[2].push("third rank item");
console.log(arr);
Вариант 2:
если у вас есть доступный пакет lodash, вы также можете использовать _.map, так как он специально предназначен для обхода разреженного массива (нативная карта пропускает неинициализированные значения)
var arr =_.map(new Array(5), (x => []))
arr[2].push("third rank item");
console.log(arr)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>
Попробуйте это, это быстрое решение для вас в одной строке.
var arr = new Array(5);
arr = Array.from(arr, x => []);
arr[2].push("third rank item");
console.log(arr);
Это происходит из-за ссылки. Массив - это тип объекта, и объект работает со своими ссылками, когда вы заполняете свой массив [] or new Array()
, заполняете только заполняемые прогоны и помещаете один и тот же массив во все индексы, поэтому при обновлении подмассива все обновляются.
Решение:
let arr = new Array(5).fill(0).map(ele => ele = []);
arr[2].push("something");
Или
let arr = Array.of([], [], [], []);
arr[2].push("something");
Результат: как и ожидалось, обновляется только 2 индекса из arr
.
Вы можете попробовать это,
var arr = new Array(5);
var i = 0;
while (i < arr.length)
arr.fill([], i++);
arr[2].push("third rank item");
console.log(arr);
Одиннадцатая строка документа ECMA Array.prototype.fill явно дает причину для тайны.
Повторите, пока к <финал
Пусть Pk будет ToString (k).
Пусть setStatus будет Set (O, Pk, значение, true).
ReturnIfAbrupt ( setStatus ) .
Увеличьте k на 1.
Здесь «значение» - это просто полученная ссылка. И они устанавливают это как свойство для массива напрямую. Это означает, что все заполненные массивы являются просто ссылкой на один объект массива.
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.