#javascript #arrays
#javascript #массивы
Вопрос:
В чем разница между этими двумя назначениями?
this.list.push(...response.data);
//vs
this.list = [].concat(this.list, response.data);
Комментарии:
1. 1-й добавляет элементы к существующим
this.list
. 2-й объединяетthis.list
иresponse.data
в новый массив и присваивает результатthis.list
.2.
this.list
Объявляется как массив для начала? Вы пробежали каждую строку? Они создают один и тот же результат? Есть ли реальная проблема или проблема, которую вы пытаетесь решить, или вам просто любопытно?3. да, это. список — это массив
4. Для получения дополнительной информации сравните push() и concat() и синтаксис Spread .
5. Это называется «оператор распространения» (также называемый «оператором splat» на других языках) developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /…
Ответ №1:
Ответ:
Первый пример:
this.list.push(...response.data);
Пример изменяет данные, используя push
. Это означает, что массив изменен на месте. Это считается «нечистым», поскольку оно не возвращает новый объект — оно изменяет данные, которые уже существуют.
Второй пример:
this.list = [].concat(this.list, response.data);
Этот пример возвращает новый объект массива. Это означает, что он соответствует функциональной парадигме. Он считается чистым, потому что он не изменяет существующий массив, он создает новый для этого случая.
Это все?
Прямо сейчас вы можете подумать: «Это то, что сказали другие ответы!«
Вы правы. Изначально я просто собирался написать дополнение, но подумал, что мог бы также кратко изложить всю информацию. Первая часть ответа кажется перефразировкой, потому что они были правильными, и…ну, вы не можете превзойти это. Однако вот что они пропустили:
Дополнительные различия:
Если бы вы заглянули внутрь concat
, вы бы увидели, что сам метод проверяет, является ли Symbol.isConcatSpreadable
это true или false . Это может навести вас на мысль, что значение if spreadable
равно true (которое по умолчанию используется в Array
Objects ), что они выполняются одинаково. Это совсем не так.
В то время как внутренне spread operator
использует элементы @@iterator
для объединения массивов / значений, Array.prototype.concat
метод построен буквально как цикл for , т.е. i=0;i<len;i ;
— Фактически, когда массив объединяется, он фактически извлекает первый элемент из вызываемого массива и выполняет утверждения и тесты, которые в противном случаененужный при использовании spread
.
Хорошо, хорошо, но что это значит?
Ну, это означает, что два примера выше могут иметь совершенно разные результаты, если вы каким-то образом настроите итератор и думаете, что объединяете массивы с spread
оператором. Результаты будут не такими, как вы ожидаете.
Это можно легко увидеть в приведенном ниже:
let a = ["a","b","c"];
let b = ["d","e","f"];
b[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
let c = JSON.stringify([].concat(a, b));
let d = JSON.stringify((a.push(...b), a));
console.log(c, d);
// a,b,c,d,e,f
// a,b,c,1,2,3
Это также означает, что, в отличие от Array.prototype.concat
метода, поскольку spread использует iterator
и, итератор может быть предоставлен / настроен вручную, и этот итератор может быть асинхронным — это открывает потенциал для использования, для которого concat
никогда не предназначался.
По сути, spread
это более округлый оператор с учетом множества различных вариантов использования, тогда concat
как буквально просто «Возьмите это и поместите это туда» с spreadable
проверкой, которая просто определяет, должен ли он выполнять мини-цикл значений внутри большего цикла for, или если внутренний-ссылки на массивы достаточно хороши.
Я надеюсь, что это ответит на ваш вопрос и даст вам более глубокое представление об операциях и о том, что на самом деле происходит под капотом!
Счастливого кодирования!
Ответ №2:
Результат будет таким же с точки зрения содержимого. Элементы, содержащиеся в response.data
, будут добавлены к this.list
.
Однако при this.list.push(...response.data)
этом список остается прежним и просто расширяется новыми элементами, поэтому список изменяется на месте. Любая ссылка на этот список приведет к изменению.
При [].concat(this.list, response.data)
этом создается новый список. Этот новый список является объединением обоих списков и затем переназначается this.list
. Итак, после назначения this.list
указывает на новый список. Любая ссылка на старый список не приведет к изменению в этом случае.
Комментарии:
1. Извините, я не видел, что вы уже ответили, пока я отвечал. Поддержал ваш, потому что вы были быстрее, и ответ правильный 🙂
2. @David, не беспокойся! Два объяснения лучше, чем одно!
3. хороший ответ! Просто чтобы вы знали, я проголосовал и добавил еще один ответ. Не потому, что вы были неправы, а потому, что было несколько вещей, которые, как я думал, вы пропустили 🙂
Ответ №3:
TL; DR
Первый нечистый, второй чистый (хотя похоже, что это делается в уже нечистом контексте).
Объяснение
Если вы используете .push
, Array
то, который .push
называется get , изменяется, потому .push
что добавляет элемент в конец существующего Array
.
.concat
вместо этого создайте новый Array
и добавьте другие Array
s к новому Array
. Таким образом, исходные Array
значения не изменяются.
Комментарии:
1. хороший ответ! Просто чтобы вы знали, я проголосовал и добавил еще один ответ. Не потому, что вы были неправы, а потому, что было несколько вещей, которые, как я думал, вы пропустили 🙂