Добавить элементы в массиве условно в JavaScript
Когда я пытаюсь объединить два объекта, используя условный оператор распространения, он работает, когда условие true
или false
:
let condition = false;
let obj1 = { key1: 'value1'}
let obj2 = {
key2: 'value2',
...(condition && obj1),
};
// obj2 = {key2: 'value2'};
Когда я пытаюсь использовать ту же логику, с массивами, она работает только тогда, когда условие true
:
let condition = true;
let arr1 = ['value1'];
let arr2 = ['value2', ...(condition && arr1)];
// arr2 = ['value2', 'value1']
Если условие false
выдается ошибка:
let condition = false;
let arr1 = ['value1'];
let arr2 = ['value2', ...(condition && arr1)];
// Error
Ответы
Ответ 1
Когда вы распространяетесь в массив, вы вызываете метод Symbol.iterator
для объекта. &&
оценивает первое значение Ложи (или последнее истинное значение, если все верно), поэтому
let arr2 = ['value2', ...(condition && arr)];
результаты в
let arr2 = ['value2', ...(false)];
Но false
не имеет метода Symbol.iterator
.
Вместо этого вы можете использовать условный оператор и распространять пустой массив, если условие ложно:
let condition = false;
let arr1 = ['value1'];
let arr2 = ['value2', ...(condition ? arr1 : [])];
console.log(arr2);
Ответ 2
false
не распространяется
Вам нужен расширяемый объект (тот, в котором реализован Symbol.iterator
), который ничего не возвращает, если распространяется.
Вы можете использовать пустой массив в качестве значения по умолчанию. Это работает, даже если arr
ложно.
let condition = false;
let arr1 = ['value1'];
let arr2 = ['value2', ...(condition && arr || [])];
console.log(arr2);
Ответ 3
Это специфика различий между синтаксисом распространения для литералов объекта и литералов массива.
MDN кратко упоминает это здесь - я подчеркиваю:
Синтаксис распространения (кроме случая свойств распространения) может применяться только к итерируемым объектам.
Разница заключается в спецификации EcmaScript 2018:
-
Относительно синтаксиса распространения объекта см. 12.2.6.8 Семантика времени выполнения: PropertyDefinitionEvaluation:
- Он вызывает
CopyDataProperties(object, fromValue, excludedNames)
где fromValue переносится в объект с ToObject
и, следовательно, становится итеративным, даже если fromValue является примитивным значением, таким как false
. Поэтому {...false}
является допустимым EcmaScript.
-
Относительно синтаксиса распространения массива см. 12.2.5.2 Семантика времени выполнения: ArrayAccumulation:
- Он просто вызывает
GetValue(spreadRef)
который не выполняет вышеупомянутую упаковку. И поэтому последующий вызов GetIterator
вызовет ошибку примитивного значения, поскольку оно не повторяется. Поэтому [...false]
является недействительным EcmaScript.