ES6——Array、Iterator接口以及遍历语法的比较

扩展运算符(spread)是三个点(...); 扩展运算符将一个数组,变为参数序列;
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5

function add(x, y) {
  return x + y;
}
var numbers = [4, 38];
add(...numbers) // 42

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
类似数组的对象,但是没有部署 Iterator 接口,使用Array.from方法转为真正的数组;(类似数组的对象,本质特征只有一点,即必须有length属性) 任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组。

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。

Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

原生具备 Iterator 接口的数据结构如下。

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • 函数的 arguments 对象
  • NodeList 对象
Iterator接口主要供for...of消费
对于普通的对象,for...in循环可以遍历键名,for...of循环会报错。

使用 Generator 函数将对象重新包装一下。

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}
for (let [key, value] of entries(obj)) {
  console.log(key, '->', value);
}

遍历语法的比较

以数组为例,JavaScript 提供多种遍历语法。最原始的写法就是for循环。

for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

这种写法比较麻烦,因此数组提供内置的 forEach 方法。

myArray.forEach(function (value, index) {
  console.log(value, index);
});

这种写法的问题在于,无法中途跳出forEach循环,break命令或return命令都不能奏效。

for…in 循环可以遍历数组的键名。

for (var index in myArray) {
  console.log(myArray[index]);
}
  • 数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。

总之,for...in循环主要是为遍历对象而设计的,不适用于遍历数组。

for...of循环相比上面几种做法,有一些显著的优点。
有着同for...in一样的简洁语法,但是没有for...in那些缺点。
不同于forEach方法,它可以与breakcontinuereturn配合使用。
提供了遍历所有数据结构的统一操作接口。

for (let value of myArray) {
  console.log(value);
}

下面是一个使用break语句,跳出for...of循环的例子。

for (var n of fibonacci) {
  if (n > 1000)
    break;
  console.log(n);
}