描述

在segmentfault上看到了一个提问,虽然被题主关闭了,但是看了下面的评论,感觉涉及的知识点还是挺多的,觉得能够好好研究一番。下面是问题的具体内容,链接在此

function add(...values) {
let sum = 0;
console.log(values);
for (var val of values) {
sum += val;
}
return sum;
}
let sun = [1, 2, 3, 4, 5, 6, 7, 8, 9, 20];
let b = [0, ...sun, 4];
console.log(add(b));

涉及的知识点

1. rest参数

function add(...values) {
console.log(values)
}
add(1, 2, 3); // [1, 2, 3]

ES6引入了rest参数(形式为...变量名

rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。(来自阮一峰老师的《ECMAScript 6 入门》)

因此,调用add函数并传入参数1, 2, 3,就能在console面板看到一个数组[1, 2, 3]

rest必须作为最后一个参数,如果function add(...values, b){}就会报错

2. for…of循环

相信很多小伙伴对for…in循环不会感到陌生,for…in 语句用于对数组或者对象的属性进行循环操作。但是for…in循环只能获得对象的key,无法直接得到value值

var arr = ['a', 'b', 'c', 'd'];

for (let a in arr) {
console.log(a); // 0 1 2 3
}

for (let a of arr) {
console.log(a); // a b c d
}

for…of 只会返回具有数字索引的属性

let arr = [3, 5, 7];
arr.foo = 'hello';

for (let i in arr) {
console.log(i); // "0", "1", "2", "foo"
}

for (let i of arr) {
console.log(i); // "3", "5", "7"
}

3. 拓展运算符“…”

console.log(...[1, 2, 3]); // 1 2 3

4. 隐式转换

加法操作符(+)如果有一个操作数是对象、数值或布尔值,则调用它们的 toString()方法取得相应的字符串值

console.log(0 + [1, 2, 3]); // '01, 2, 3'

解析

function add(...values) {
let sum = 0;
console.log(values); // [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 4]]
for (var val of values) {
sum += val;
// val = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 4],
// 所以0+[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 4],执行隐式转换,会把b转换为'0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 4',结果为'00,1,2,3,4,5,6,7,8,9,20,4'
}
return sum;
}
let sun = [1, 2, 3, 4, 5, 6, 7, 8, 9, 20];
let b = [0, ...sun, 4]; // 即b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 4]
console.log(add(b));