题目
let a = [
{ one: 1, two: 2 },
{ one: 3, two: 4 },
{ one: 5, two: 6 }
];
对数组a进行运算,要求得到结果:{ one: 9, two: 12 }
解答
最简单的思路,遍历数组并进行成员相加,代码如下:
let sum = { one: 0, two: 0 };
for(let i = 0; i < a.length; i++) {
sum.one += a[i].one;
sum.two += a[i].two;
}
console.log(sum);
迭代1
上面的代码中,通过索引i
去查找元素不如直接遍历数组中的元素,即使用forEach
替换for
,代码修改如下:
let sum = { one: 0, two: 0 };
a.forEach(item => {
sum.one += item.one;
sum.two += item.two;
})
console.log(sum);
迭代2
上面的代码,运行时没有任何问题,但是考虑一下:如果成员属性多了一个怎么办,比如:{ one: 1, two: 2, three, 3 }
?
因此,在代码中hardcodeone
、 two
是非常不好的习惯,代码修改如下:
let sum = {};
a.forEach(item => {
Object.keys(item).forEach(key => {
if (sum[key] === undefined) sum[key] = 0;
sum[key] += item[key];
});
})
console.log(sum);
迭代3
其实针对这种累加场景,ES5增加了reduce
函数:
reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,将其减少为单个值。
使用reduce
函数重写:
let sum = a.reduce((pre, curr) => {
Object.keys(curr).forEach(key => {
if (pre[key] === undefined) pre[key] = 0;
pre[key] = pre[key] + curr[key];
});
return pre;
}, {})
console.log(sum);
迭代4
使用三目运算符重写Object.keys(curr).forEach()
中的代码:
let sum = a.reduce((pre, curr) => {
Object.keys(curr).forEach(key => {
pre[key] = pre[key] ? pre[key] + curr[key] : curr[key];
});
return pre;
}, {})
console.log(sum);
for VS forEach
for
是js中的一个流程控制关键字,而forEach
是数组对象的一个方法:
forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(例如在稀疏数组上)。callback 函数会被依次传入三个参数:当前项的值、当前项的索引和数组对象本身。
从MDN上的描述可以看到,使用forEach
有以下几个优势:
- 更有语义化
- 在稀疏数组上效率更高
- 更方便的得到当前项的值(
for
循环还需要通过[]
运算符取值) - 减少不必要的变量声明,比如下述代码:
Object.keys(curr).forEach(key => {})
const keys = Object.keys(curr);
for (let i = 0; i < keys.length; i++) {
// do something with keys[i]
}
undefined?
undefined
是JavaScript内置类型之一,可以使用typeof
来返回其类型的字符串值:
typeof undefined === 'undefined' // true
- 对于一个未初始化的变量,其值为
undefined
:
var a;
a === undefined // true
- 使用一个不存在(未声明)的变量,会先抛出
ReferenceError
异常:
try {
b === undefined
} catch(err) {
console.log(err) // ReferenceError: b is not defined
}
- 对不存在(未声明)的变量使用
typeof
来检查,却可以正常执行并返回undefined
值:
typeof b === 'undefined' // true
- 对于对象中不存在的属性,其值也为
undefined
:
var obj = {};
obj.a === undefined // true
总结
最终代码如下:
let a = [
{ one: 1, two: 2 },
{ one: 3, two: 4 },
{ one: 5, two: 6, three: 7 }
];
let sum = a.reduce((pre, curr) => {
Object.keys(curr).forEach(key => {
pre[key] = pre[key] ? pre[key] + curr[key] : curr[key];
});
return pre;
}, {})
console.log(sum);