目录

1. 操作与数据类型

2.迭代器

3. 实现迭代器接口

1. 操作与数据类型

四个操作与五种数据类型的关系:(直接使用)

string

array

object

map

set

for...in

不行

不行

forEach

不行

不行

for...of

不行

... (扩展运算符)

不行

其中有几点你需要知道:

  1. for in遍历键(索引),for of遍历值(必须是可迭代对象,遍历的是什么也可以自己手动修改),forEach可以传入的方法接收只读的传入数据类型三个参数。
  2. for of与...扩展运算符能调用都是因为他们实现了Symbol.interator接口!所以理论上任何数据类型都可以使用他们,只要实现了Symbol.interator接口。
  3. string类型也实现了Symbol.interator接口,只不过是实现在包装类型String上,我们可以通过new String()来创造一个包装类型的对象,然后就能看到Symbol.interator的具体实现了。
  4. object使用for in时,不会遍历symbol类型的键。
  5. object可以在新建对象时使用扩展运算符!如const obj1 = { a:1, ...obj }

2.迭代器

迭代器是es6新增加的功能,以满足各种数据类型的迭代需要,es6本身就实现了许多数据类型的迭代器:

1. Array
2. string(实现在包装类String上,可以使用String()手动创造包装类对象)
3. Set
4. Map
5. arguments对象
6. NodeList等DOM集合类型

这也就代表了,我们不用任何操作,就可以使用for of和...对它们进行操作。

需要注意,在一个函数中,我们可以通过arguments和...params(变量名可以自定义)一次性接收不限数量的参数,而且它们都可以使用for of与...扩展运算符,但是他们是不同的!arguments是一个伪数组,而params是真真正正的数组。

比如如下代码:

function f(...params){
    console.log(params)
    console.log(arguments)
}
f(1,2,3)

输出值如下:

es script 里 for 循环_ecmascript

我们可以看到它们是有些不同点的,我们可以如此理解:

  1. 使用...运算符的params变量是一个数组,它的原型是Array,我们能够进行迭代的原因是Array原型上面实现了Symbol.interator接口。
  2. arguments变量不是一个数组(只是一个伪数组),它的原型是Object,我们能够进行迭代的原因是arguments本身就实现了Symbol.interator接口,即arguments[Symbol.interator]。

因此,如果你希望使用真数组,那么使用...params接收参数将会是不错的选择;但是,如果你在某些情况下不得不使用arguments这个伪数组,你可以使用const arr = [ ...arguments ]来将伪数组转换为真数组!事实上,任何可迭代的数据类型都可以这样转换。

需要注意,es6的箭头函数不能使用arguments,只能使用...扩展运算符!

3. 实现迭代器接口

接下来我们来手动实现一个简易的迭代器接口

以下仅是示例,不推荐真的对原始值的包装类型进行修改!一般在自己定义的对象或者类上面进行如下操作!

今天,程序员小A想:我想执行一个语句块50次,一般使用for(let i = 0;i < 50;i++) { ... },能不能有更简便的写法,以达到相同的效果呢?比如使用for of这种语法,一个for(const i of 50) { ... } 不就解决问题了吗?

他写下了如下代码:

for(const i of 5){
    console.log(i)
}

但是,他发现浏览器报了这个错误!

es script 里 for 循环_数组_02

 “5是不可迭代的”,那我们就手动让它可迭代!

Number.prototype[Symbol.iterator] = function(){
    const max = this.valueOf()
    let count = 0
    return {
        next(){
            if(count < max){
                return {done:false , value:count++}
            } else {
                return {done:true , value:undefined}
            }
        }
    }
}


for(const i of 5){
    console.log(i)
}

可以看到,达到了他想要的效果!

es script 里 for 循环_es script 里 for 循环_03

同样的,...扩展运算符也可以使用了!

console.log(...50)

es script 里 for 循环_数组_04

 这样我们就成功的手动实现了迭代器接口!