JavaScript 减少和解构问题
JavaScript reduce and destructuring question
我目前正在学习 James Moore 的面向初学者的函数式编程 JavaScript Udemy 课程。我在理解一段代码的工作原理时遇到了一些困难:
const grades = [22, 77, 89, 90, 45, 77, 87, 92, 66, 44, 74, 81, 82, 81, 97];
const gradeCount = grades.reduce(computer, {});
function computer(acc, grade){
const {a = 0, b = 0, c = 0, d = 0, f = 0} = acc;
if (grade >= 90){
return {...acc, a: a + 1};
} else if (grade >= 80){
return {...acc, b: b +1};
} else if (grade >= 70){
return {...acc, c: c + 1};
}else if (grade >= 60){
return {...acc, d: d + 1};
} else {
return {...acc, f: f + 1};
}
}
console.log(gradeCount);
我的第一个问题是;为什么这里使用解构而不是 const a=0, b=0, c=0, d=0, f=0;
?与原始技术相比,这似乎没有那么冗长?
其次,为什么 reduce 方法 returns 一个包含所有等级及其相应数量的对象,而不是每个等级一个单独的对象?
提前感谢您的任何建议。
My first question is; why is destructuring used here as opposed to
const a=0, b=0, c=0, d=0, f=0;? This seems far less verbose when
compared to the original technique?
所以通常的变量赋值方式是这样的。
const obj = {
a: 'A',
b: 'B',
c: 'C',
d: 'D',
e: 'E'
}
let a = obj.a || 0,
b = obj.b || 0,
c = obj.c || 0,
d = obj.d || 0,
e = obj.e || 0;
你看到这是多少代码了吗?让我们使用解构来实现相同的目的。
let {a = 0, b = 0, c = 0, d = 0, e = 0} = obj;
这要好得多并且做同样的事情。它正在定义来自 a to e
的变量并设置 default value to 0
.
如果您必须从对象中获取嵌套值,那么 destructuring
会更容易。
const user = {
name: {
firstName: 'John',
lastName: 'Doe'
},
age: '26'
}
let {name: {firstName, lastName}, age} = user;
让我们看看如何在函数参数中使用解构。所以我们有一个 user
对象,它是用户的 returns fullName
。如果 firstName
或 lastName
为空,那么我们必须获取默认名称。
这是我们通常的做法:
function getUserFullName(user) {
let firstName = user.firstName || 'Jane';
let lastName = user.lastName || 'Doe';
return firstName + ' ' + lastName;
}
const user = {
name: {
firstName: 'John',
lastName: 'Doe'
},
age: '26'
}
getUserFullName(user);
使用解构的同样的事情可以这样完成:
function getUserFullName({name: {firstName = 'Jane', lastName = 'Doe'}} = user) {
return `${firstName} ${lastName}`;
}
const user = {
name: {
firstName: 'John',
lastName: 'Doe'
},
age: '26'
}
getUserFullName(user);
一开始可能会感到困惑,但一旦开始使用它,您就会意识到它的便利性。
Secondly, why is it that the reduce method returns one object
containing all the grades with their corresponding quantities as
opposed to a separate object for each grade?
这是因为computer
方法returns一个包含所有成绩的对象。
return {...acc, a: a + 1};
要知道为什么你需要知道reduce方法是如何工作的。来自 MDN 文档:
The reduce() method executes a reducer function (that you provide) on
each element of the array, resulting in a single output value
所以每次调用 computer
方法时,acc
、grade
和 returns 都在最后一个值。
My first question is; why is destructuring used here as opposed to const a=0, b=0, c=0, d=0, f=0;
? This seems far less verbose when compared to the original technique?
如果您按照建议声明变量,您将不会从对象中获取以前的值:
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);
这并没有回退到零只是为了清楚发生了什么。后备值可以用 the conditional operator ? :
完成,看起来像这样:
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}
`)
或者,an idiomatic usage of the OR operator ||
也可以产生后备值:
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;
Secondly, why is it that the reduce method returns one object containing all the grades with their corresponding quantities as opposed to a separate object for each grade?
嗯,这就是 Array#reduce
的工作原理。我将简化一些事情并为简洁起见跳过不相关的细节 - 请随意阅读 MDN 文档,因为它比我在这里要全面得多。
reduce
的形式为:
<array>.reduce(callback, initialValue)
你为它提供一个回调函数,该函数将使用两个参数为数组中的每个项目调用一次:
function callback(previousResult, currentItem){}
- 回调函数的上一个结果。除非这是第一次调用它,否则它将使用提供给
.reduce
的 initialValue
。
- 注意 -
previousResult
经常被命名为 prev
for "previous" 或 acc
for "accumulator"。为了清楚起见,我选择了长格式,但正如您在代码中看到的那样,它是 acc
- 这是该参数的惯用名称。
- 当前正在操作的项目。项目将按顺序一一访问。
使用简单的 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
属性,那么它将被添加并且由于 variable 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);
我目前正在学习 James Moore 的面向初学者的函数式编程 JavaScript Udemy 课程。我在理解一段代码的工作原理时遇到了一些困难:
const grades = [22, 77, 89, 90, 45, 77, 87, 92, 66, 44, 74, 81, 82, 81, 97];
const gradeCount = grades.reduce(computer, {});
function computer(acc, grade){
const {a = 0, b = 0, c = 0, d = 0, f = 0} = acc;
if (grade >= 90){
return {...acc, a: a + 1};
} else if (grade >= 80){
return {...acc, b: b +1};
} else if (grade >= 70){
return {...acc, c: c + 1};
}else if (grade >= 60){
return {...acc, d: d + 1};
} else {
return {...acc, f: f + 1};
}
}
console.log(gradeCount);
我的第一个问题是;为什么这里使用解构而不是
const a=0, b=0, c=0, d=0, f=0;
?与原始技术相比,这似乎没有那么冗长?其次,为什么 reduce 方法 returns 一个包含所有等级及其相应数量的对象,而不是每个等级一个单独的对象?
提前感谢您的任何建议。
My first question is; why is destructuring used here as opposed to const a=0, b=0, c=0, d=0, f=0;? This seems far less verbose when compared to the original technique?
所以通常的变量赋值方式是这样的。
const obj = {
a: 'A',
b: 'B',
c: 'C',
d: 'D',
e: 'E'
}
let a = obj.a || 0,
b = obj.b || 0,
c = obj.c || 0,
d = obj.d || 0,
e = obj.e || 0;
你看到这是多少代码了吗?让我们使用解构来实现相同的目的。
let {a = 0, b = 0, c = 0, d = 0, e = 0} = obj;
这要好得多并且做同样的事情。它正在定义来自 a to e
的变量并设置 default value to 0
.
如果您必须从对象中获取嵌套值,那么 destructuring
会更容易。
const user = {
name: {
firstName: 'John',
lastName: 'Doe'
},
age: '26'
}
let {name: {firstName, lastName}, age} = user;
让我们看看如何在函数参数中使用解构。所以我们有一个 user
对象,它是用户的 returns fullName
。如果 firstName
或 lastName
为空,那么我们必须获取默认名称。
这是我们通常的做法:
function getUserFullName(user) {
let firstName = user.firstName || 'Jane';
let lastName = user.lastName || 'Doe';
return firstName + ' ' + lastName;
}
const user = {
name: {
firstName: 'John',
lastName: 'Doe'
},
age: '26'
}
getUserFullName(user);
使用解构的同样的事情可以这样完成:
function getUserFullName({name: {firstName = 'Jane', lastName = 'Doe'}} = user) {
return `${firstName} ${lastName}`;
}
const user = {
name: {
firstName: 'John',
lastName: 'Doe'
},
age: '26'
}
getUserFullName(user);
一开始可能会感到困惑,但一旦开始使用它,您就会意识到它的便利性。
Secondly, why is it that the reduce method returns one object containing all the grades with their corresponding quantities as opposed to a separate object for each grade?
这是因为computer
方法returns一个包含所有成绩的对象。
return {...acc, a: a + 1};
要知道为什么你需要知道reduce方法是如何工作的。来自 MDN 文档:
The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value
所以每次调用 computer
方法时,acc
、grade
和 returns 都在最后一个值。
My first question is; why is destructuring used here as opposed to
const a=0, b=0, c=0, d=0, f=0;
? This seems far less verbose when compared to the original technique?
如果您按照建议声明变量,您将不会从对象中获取以前的值:
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);
这并没有回退到零只是为了清楚发生了什么。后备值可以用 the conditional operator ? :
完成,看起来像这样:
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}
`)
或者,an idiomatic usage of the OR operator ||
也可以产生后备值:
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;
Secondly, why is it that the reduce method returns one object containing all the grades with their corresponding quantities as opposed to a separate object for each grade?
嗯,这就是 Array#reduce
的工作原理。我将简化一些事情并为简洁起见跳过不相关的细节 - 请随意阅读 MDN 文档,因为它比我在这里要全面得多。
reduce
的形式为:
<array>.reduce(callback, initialValue)
你为它提供一个回调函数,该函数将使用两个参数为数组中的每个项目调用一次:
function callback(previousResult, currentItem){}
- 回调函数的上一个结果。除非这是第一次调用它,否则它将使用提供给
.reduce
的initialValue
。- 注意 -
previousResult
经常被命名为prev
for "previous" 或acc
for "accumulator"。为了清楚起见,我选择了长格式,但正如您在代码中看到的那样,它是acc
- 这是该参数的惯用名称。
- 注意 -
- 当前正在操作的项目。项目将按顺序一一访问。
使用简单的 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
属性,那么它将被添加并且由于 variable 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);