带你详细了解ES6中的Iterator

413 阅读3分钟

前言

迭代器(Iterator),是 ES6 引入的一种新的遍历机制,这篇文章呢带大家详细了解一下ES6中的Iterator。

hasOwnProperty方法

这个方法是在对象的原型上,给实例对象用的,用来判断是否具有自己的属性。

1.png 我们具体来看一下是怎么用的,for in 遍历对象或数组具有以下特点:

  1. 循环返回的是对象的键名
  2. 遍历数组返回的是下标
  3. 不仅可以遍历显示具有的属性,还可以遍历到对象原型上的属性

大家看第三点,怎样让它遍历不到对象原型上的属性呢,因为大多数时候我们不需要原型上的属性。这就可以用hasOwnProperty方法来解决。

 let obj = {
   a: 1
 }
 let obj2 = Object.create(obj)
 obj2.aa = 100
 obj2.bb = 200
 
let res = []
for (let key in obj2) {
    // 判断该key是否为obj2显示具有的属性
    if (obj2.hasOwnProperty(key)) {
        res.push(obj2[key])
    }
}
console.log(res);

上述代码结果为[100,200],这样就遍历不到原型上的属性了。如果遍历数组的话,虽然数组原型上不具有此方法,但是数组也是对象创建的,也可以继承到此方法。

一些数组身上的遍历方法

for循环

for (let i = 0; i < arr.length; i++) {}

forEach

arr.forEach((item, index, arr) => {})

map

arr.map((item, index, arr) => { return XXX })

reduce

let sum = arr.reduce((pre, item, inde, arr) => { return pre + item }, 0)

filter

arr.filter((item, index, arr) => { return item > 2 })

(把满足条件的过滤出来,有返回值,返回值为数组)

ES6新增的遍历数组方法(for of)

for of遍历有以下特点:

  1. 遍历数组返回的是元素
  2. 不能遍历不具有 iterator 属性的数据结构
  3. 不能遍历到数组原型上的属性
Array.prototype.d = 'd'
const arr = [1, 2, 3, 4]

for (let item of arr) { // obj is not iterable
    console.log(item);
}

结果为:1 2 3 4

接下来就深入了解一下Iterator

Iterator

概念

迭代器(Iterator)是一个统一的接口,它的作用是使各种数据结构可被便捷的访问,它是通过一个键为Symbol.iterator的方法来实现。

原理

通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置;随后通过 next 方法进行向下迭代指向下一个位置,next 方法会返回当前位置的对象,对象包含了 valuedone 两个属性,value 是当前属性的值,done 用于判断是否遍历结束;当 donetrue 时则遍历结束。

2.png

应用

问题:用迭代器遍历数组,让数组的每一项都乘2。

let arr = [1, 2, 3]

function each(arr) {
    let res = []
    let it = arr[Symbol.iterator]()

    function deep() {
        let current = it.next()
        //遍历完毕退出
        if (current.done) {
            return
        }
        res.push(current.value * 2)
        //递归
        deep()
    }
    deep()
    return res
}

let newArr = each(arr) // [2, 4, 6]
console.log(newArr);

结果为:[2,4,6]

实现(面试考点)

面试官问:你能不能实现让下面的代码a的值为1,b的值为2

let [a, b] = { a: 1, b: 2 } 

console.log(a, b);

首先,我们应该想着让{ a: 1, b: 2 } 这个对象具有可迭代属性;在对象原型上挂上[Symbol.iterator],返回出一个数组[1,2]。对象身上有个方法Object.values(obj)可以以数组的形式返回出键值,得到数组就可以用[Symbol.iterator]了。

Object.prototype[Symbol.iterator] = function () {
    // 返回一个 Array 类型的可迭代对象
    return Object.values(this)[Symbol.iterator]()
}

let [a, b] = { a: 1, b: 2 } // [1, 2]

console.log(a, b);

这样就不报错了。

结语

迭代器(Iterator)在我们日常开发过程中用得比较少,但是了解此原理对我们学习是有帮助的,这也是面试的常考点。