Мой первый вопрос: почему здесь используется деструктуризация, а не const a=0, b=0, c=0, d=0, f=0;
? Это кажется гораздо менее многословным по сравнению с оригинальной техникой?
Если вы объявите переменные так, как вы предлагаете, вы не получите предыдущие значения из объекта:
function original(obj) {
const { a=0, b=0, c=0, d=0, f=0 } = obj;
console.log(`const { a=0, b=0, c=0, d=0, f=0 } = obj;
a = ${a}
b = ${b}
c = ${c}
d = ${d}
f = ${f}
`);
}
function proposed(obj) {
const a=0, b=0, c=0, d=0, f=0;
console.log(`const a=0, b=0, c=0, d=0, f=0;
a = ${a}
b = ${b}
c = ${c}
d = ${d}
f = ${f}
`);
}
const obj = { a: 1, b: 2, d: 4};
original(obj);
proposed(obj);
Уничтожение заберет свойство a
у объекта на правой стороне =
и присвоит ноль только в том случае, если он его не найдет. Итак, это похоже на непосредственное получение свойств:
function explicit(obj) {
const a = obj.a,
b = obj.b,
c = obj.c,
d = obj.d,
f = obj.f;
console.log(`const a = obj.a, b = obj.b, c = obj.c, d = obj.d, f = obj.f;
b = ${b}
c = ${c}
d = ${d}
f = ${f}
`);
}
const obj = { a: 1, b: 2, d: 4};
explicit(obj);
Это не имеет отступления к нулю только для ясности того, что происходит. Резервное значение можно сделать с помощью условного оператора ? :
, который будет выглядеть следующим образом:
const obj = {b: 2};
const a = obj.a ? obj.a : 0;
const b = obj.b ? obj.b : 0;
console.log(`Using the conditional operator "? :"
a = ${a}
b = ${b}
`)
В качестве альтернативы, идиоматический c использует оператор ИЛИ ||
, который также может давать запасное значение:
const obj = {b: 2};
const a = obj.a || 0;
const b = obj.b || 0;
console.log(`Using the OR operator "||"
a = ${a}
b = ${b}
`)
Они не полностью и не дают значения по умолчанию при деструктуризации, но, по крайней мере, достаточно близки для иллюстрации альтернативы. Разница в том, как обрабатываются ложные значения, но мы можем пока игнорировать это.
Таким образом, с учетом этого, деструктуризация на намного менее многословна, чем обычный способ:
const a = obj.a || 0,
b = obj.b || 0,
c = obj.c || 0,
d = obj.d || 0,
f = obj.f || 0;
//compared with
const { a=0, b=0, c=0, d=0, f=0 } = obj;
Во-вторых, почему метод Reduce возвращает один объект, содержащий все оценки с соответствующими количествами, а не отдельный объект для каждой оценки?
Ну, это как работает Array#reduce
. Я собираюсь немного упростить вещи и пропустить нерелевантные детали для краткости - не стесняйтесь читать документацию по MDN, поскольку она намного более тщательна, чем я буду здесь.
Форма reduce
такая:
<array>.reduce(callback, initialValue)
Где вы предоставляете ему функцию обратного вызова, которая будет вызываться один раз для каждого элемента в массиве с двумя параметрами:
function callback(previousResult, currentItem){}
- previous результат функции обратного вызова. Если это не первый раз, когда он вызывается, в этом случае он будет использовать
initialValue
, предоставленный .reduce
. - note -
previousResult
очень часто называют prev
для "предыдущего" или acc
для "аккумулятора". Для ясности я выбрал длинную форму, но, как вы можете видеть, в вашем коде acc
- это идиоматическое c имя для этого параметра.
- Текущий элемент прооперирован Элементы будут последовательно посещаться последовательно.
Быстрая иллюстрация с использованием простого reduce
для суммирования всех элементов в массиве:
callback = (acc, currentNumber) => acc + currentNumber;
initialValue = 0;
[1, 2, 3].reduce(callback, initialValue);
затем шаги .reduce
будет показано здесь:
[3, 5, 7]
^ ^ ^
---------------------- | |
acc = 0 | | |
currentNumber = 3 | | |
result = 3 | | |
------------------- | |
| |
--------------------------- |
acc = 3 | |
currentNumber = 5 | |
result = 8 | |
------------------- |
|
--------------------------------
acc = 8 |
currentNumber = 7 |
result = 15|
-------------------
То же самое относится к коду в вопросе - каждый раз, когда только обратный вызов генерирует одиночный объект, поэтому в следующий раз он будет вызван acc
снова получит один объект.
Наконец, способ обновления объекта на с использованием нотации распространения объекта ...
для клонирования и изменения значения . {...acc}
создаст новый объект, который имеет те же значения, что и предыдущий, а {...acc, a: a + 1}
клонирует его и изменит свойство a
на значение переменной a
плюс 1. Если раньше свойства a
не было, оно будет добавлено и, поскольку переменная a
будет равна нулю, вы получите { a: 1 }
.
const initial = { a: 5};
const obj1 = {...initial, a: 6};
console.log("obj1", obj1);
const obj2 = {...obj1, b: 1};
console.log("obj2", obj2);
const obj3 = {...obj2, b: 2};
console.log("obj3", obj3);