深入浅出ES6——迭代器的演变

在JavaScript刚刚开始萌生的时候,我们通常使用这种方式遍历数组

let arr1 = [1, 2, 3, 4];

for (let index = 0; index < arr1.length; index++) {
    const element = arr1[index];
    console.log(element); // 1 2 3 4
}

自从ES5 正式发布之后,我们可以使用 forEach 方法来遍历数组.

let arr2 = [1, 2, 3, 4];

arr2.forEach( item => {
    if (item === 3) return
    console.log(item); // 1 2 4
})
  • 显然的,这段代码看起来更加简洁,但是并没有按照我们预期的进行终结遍历。
  • 在文档中我们可以看到描述 forEach() 方法对数组的每个元素执行一次提供的函数。 意思就是即使你在某个函数中return了也只是终结了当次函数的执行。

那么,你一定想尝试一下 for-in 循环

let arr3 = [1, 2, 3, 4];

for (const index in arr3) {
    if (index === 3) break
    console.log(index);   // 0 1 2 3
    console.log(typeof index); // string
}

程序再次没有按照我们预期的运行:

  • 在这段代码中,赋值给index的值并不是实际的数字,可以看到输出的是string '0' '1' '2' '3', 因此如果在这之前你并没深入理解,可能会掉进坑里,此时我们可以把 === 改成 == 即可

  • for...in 循环只遍历可枚举属性。像Array和Object使用内置构造函数所创建的对象都会继承自Object.prototype 和 String.prototype的不可枚举属性, 如果在原型上自定义了属性,那么稍微不注意将会导致如下错误:

let arr3 = [1, 2, 3, 4];

Array.prototype.name = '看看我被遍历了没';

for (const key in arr3) {

    // 将额外的遍历属性
    // const element = arr3[key];
    // console.log(element); // 1 2 3 4 '看看我被遍历没'

    // 正确做法
    if (arr3.hasOwnProperty(key)) {
        const element = arr3[key];
        console.log(element); // 1 2 3 4
    }
}

  • 更加可怕的是,由于迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。

  • 简而言之, for-in 是为普通对象设计的,你可以遍历得到字符串类型的键,因此不适用于数组遍历。

更好的选择 for-of 循环

在ES6中增加了一种新的循环语法来解决目前的问题:

for (variable of iterable) {
    //statements
}

for...of 可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。

  • 这是最简洁、最直接的遍历数组元素的语法

  • 这个方法避开了 for-in 循环的所有缺陷

  • 与forEach不同的是,它可以正确响应 break、continue 和 return 语句

  • 未来的 JS 可以使用一些新型的集合类,甚至会有更多的类型
    陆续诞生,而 for-of 就是为遍历所有这些集合特别设计的循环语句

  • for-of 循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用 for-in 循环(这也是它的本职工作)或内建的 Object.keys()方法:

// 向控制台输出对象的可枚举属性
for (var key of Object.keys(someObject)) {
    console.log(key + ": " + someObject[key]);
}

深入理解

“能工摹形,巧匠窃意.” -- 巴勃罗·毕加索

ES6始终坚信这样的宗旨: 凡是新加入的特性,势必已在其他语言中得到强有力的实用性证明。
举个例子,新加入的for-of 循环像极了C++、Java、C#以及Python中的循环语句。与他们一样,这里的 for-of 循环支持语言和标准库中提供的几种不同的数据结构,它同样也是这门语言中的一个扩展点。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。