То, о чем вы просите, в настоящее время невозможно с использованием литерала массива и синтаксиса распространения. Это связано с тем, что, в отличие от литералов объектов, массив определяется не конкретными индексами, а последовательностью, которая становится его элементами.
В лучшем случае вы можете использовать elision, чтобы оставить индекс пустым, например, [1, , 3]
создаст 1, <empty>, 3
, но вы все равно должны указать это явно, вы не можете пропустить, это означает, что создание массива только с первым и десятым элементом становится очень сложным [1,,,,,,,,,10]
. Определенно не рекомендуется иметь больше в качестве литерала массива.
При этом синтаксис распространения ...
с массивами принимает значения из итератор, поэтому [...arr]
похож на:
let result = [];
let it = arr[Symbol.iterator]();
let next = it.next();
while (!next.done)) {
result.push(next.value);
next = it.next();
}
Зная это, мы можем использовать функции-генераторы и создайте несколько простых общих вспомогательных генераторов, которые преобразуют итерацию и распространяют свои результаты. Например
Получить все, кроме последнего элемента, из итерации:
/**
*
* @generator
* @param {Iterable}
* @yields {*} every value from the iterable but the last one
*/
function* initial(iterable) {
const it = iterable[Symbol.iterator]();
let last = it.next();
let next = it.next();
while(!next.done){
yield last.value;
last = next;
next = it.next();
}
}
const arr = [1, 2, 3];
const modifiedClone = [...initial(arr), 4];
console.log(modifiedClone);
Возьмите первые значения num
из итерации:
/**
*
* @generator
* @param {number} num - how many items to extract
* @param {Iterable} itearable - iterable from where the results should be extracted
* @yields {*} - at most `num` amount of results from `iterable`
*/
function* take(num, iterable) {
const it = iterable[Symbol.iterator]();
let {value, done} = it.next();
for (let i = 0; i < num && !done; i++, {value, done} = it.next()) {
yield value;
}
}
const arr = [1, 2, 3];
const modifiedClone = [...take(arr.length - 1, arr), 4];
console.log(modifiedClone);
Перейдите к итерации и преобразуйте значение там, где это необходимо:
/**
* transform an iterable of key-value pairs by their key
*
* @generator
* @param {Map} replacements - new values for each of the keys
* @param {Iterable} keyValueIterable - iterable which produces `[key, value]` pairs
* @yields {*} - the values of the iterable transformed where needed
*/
function* replaceByKey(replacements, keyValueIterable) {
const it = keyValueIterable[Symbol.iterator]();
for (let {value: pair, done} = it.next(); !done; {value: pair, done} = it.next()) {
let [key, value] = pair;
if (replacements.has(key))
yield replacements.get(key);
else
yield value;
}
}
const arr = ["a", "b", "c", "d", "e"];
const replace = new Map()
.set(1, "foo")
.set(arr.length-1, "bar");
const modifiedClone = [...replaceByKey(replace, arr.entries())];
console.log(modifiedClone);
Дополнительные возможности доступны в зависимости от того, что вам нужно.
04.12.2020