We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
可迭代(Iterable) 对象是数组的泛化。这个概念是说任何对象都可以被定制为可在 for..of 循环中使用的对象。
数组是可迭代的。但不仅仅是数组。很多其他内建对象也都是可迭代的。例如字符串也是可迭代的。
Iterator 就是针对那么多可迭代的数据结构中是一种统一的接口机制,只要部署了这个接口,就可以被依次遍历处理。
Iterator 的遍历过程是这样的:
{value:any,done:boolean}
下面我们通过一个例子快速了解核心概念。
需要知道的是,对象默认是没有 Iterator 接口的,所以它不能被 for..of 循环。这里我们手动给它设置 Iterator 接口。
let range={ from:0, to:5 }
如果能让上面的range对象通过for..of循环打印出0、1、2、3、4、5。这就代表 iterator 接口部署成功了
range
for..of
1.首先我们要给它设置一个属性,这个属性只能通过Symbol.iterator访问,这个属性保存一个函数。
range[Symbol.iterator]=function(){}
这个 Symbol.iterator是部署的开始,当 for..of 开始循环时,会调用Symbol.iterator函数 2.Symbol.iterator函数会返回一个对象,内部有一个 next 方法,并返回{value:xxx,done:boolean}这样的对象。
Symbol.iterator
{value:xxx,done:boolean}
// 由for...of 调用range[Symbol.iterator]()并返回 Iterator 对象 range[Symbol.iterator]=function(){ // 返回一个iterator 对象 return { first:0, last:5, next(){ //这里的 this 指向iterator 对象,由 for..of 每次循环时自动调用该对象的 next 方法 if(this.first<=this.last){ return {value:this.first++,done:false} }else{ return {done:true} } } } }
3.打印信息
for(let i of range){ alert(i) }
会依次打出0-5的数,Iterator接口部署成功了。
Iterator
如果需要部署 Iterator 接口,我们需要手动添加 Symbol.Iterator属性。
这个属性保存着一个函数,当 for..of 开始时,就会调用该函数,并返回Iterator 对象,此时指针初始化。
Iterator对象内部保存着一个 next 函数,for..of 的每次循环都会调用到Iterator对象中的next 函数,所以这时候的 this 指向 Iterator 对象。
next函数会返回{value:xx,done:boolean}的数据结构。 当 done 为 true 时,循环停止。
{value:xx,done:boolean}
for..of循环每次都会取返回结果的value属性
value
数组跟字符串内置了 Iterator 接口,所以我们可以直接使用 for..of来循环,比如下面的字符串
for(let str of 'strings'){ console.log(str) } // s t r i n g s
下面我们直接获取它的Symbol.iterator属性,来看看到底发生了什么。
我们已经知道这个属性保存着一个函数,这个函数会返回 Iterator 对象,所以我们直接调用拿到这个对象。
let strings='strings' let Iterator=strings[Symbol.iterator]()
这个对象内部会执行 next 方法,返回{value:xx,done:boolean}对象
Iterator.next() //{value: "s", done: false}
现在我们得出一个结论:可迭代对象就是内部部署了 Iterator接口的对象,这个部署 Iterator 接口的标志是内部有 [Symbol.iterator]属性。
[Symbol.iterator]
我们可以通过浏览器打印出来看一下,比如例子中的strings 的原型上就有[Symbol.iterator]属性,它是一个函数。
strings
我们直接调用这个方法,然后看看内部到底是个啥
可以看到返回的StringIterator 的原型上有个 next 方法。
可迭代对象的概念就是实现[Symbol.iterator]方法的对象
伪数组和数组一样,本质上是个对象,但是数组有数组原型(Array.prototype),而伪数组没有数组原型。
Array.prototype
通过上面的截图我们知道[Symbol.iterator]会部署在原型上,比如数组原型、字符串原型里就有部署这个属性。
对象以及其原型是没有部署 Iterator 接口的。伪数组既然没有数组的原型,那就不一定有 Iterator 接口。
比如下面是一个伪数组
let arrayLike = { // 有索引和 length 属性 => 类数组对象 0: "Hello", 1: "World", length: 2 };
它的原型直接连接到 Object.prototype 上,所以它没有数组的共用方法。比如 push,pop 等等。
Object.prototype
push
pop
如果希望实现,那可以采用Array.from。
Array.from
Array.from(arrayLike)
这样这个伪数组就具备 Iterator 接口了。
有没有一种伪数组虽然没有数组的原型,但是却默认部署 Iterator 接口的呢?
有的,任何可以被扩展运算符变成数组的伪数组都有Iterator接口。
比如arguments虽然没有数组的原型,但是却具有 [Symbol.iterator] 接口
arguments
也许你会认为扩展运算符能把所有伪数组变成数组,不过这只对了一半。
扩展运算符只能把已经具备 Iterator 接口的数据变成数组。不信我们看
结论就是只要你部署了Iterator 接口,才能用扩展运算符转化为数组。可不要弄反顺序噢。
Iterator 是一个接口,具备 Iterator 接口的特点是内部有[Symbol.iterator]属性。这个属性保存着一个会返回 Iterator 对象的函数。
Iterator对象内部具备 next 方法,会返回键名为 done 和 value 的对象。
for..of 遍历器为部署了 Iterator 接口的数据结构而生,当使用 for..of 遍历时,会首先调用[Symbol.iterator] 方法,生成Iterator对象,每次循环都会调用这个对象内部的 next 方法。
有一些伪数组没有部署Iterator 接口,所以不能被扩展运算符转化为数组。这时候需要采用 Array.from方法。
Symbol.iterator 方法会被 for..of 自动调用,但我们也可以直接调用它。
内置的可迭代对象例如字符串和数组,都实现了 Symbol.iterator。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
Iterator(迭代器)
什么是Iterator
可迭代(Iterable) 对象是数组的泛化。这个概念是说任何对象都可以被定制为可在 for..of 循环中使用的对象。
数组是可迭代的。但不仅仅是数组。很多其他内建对象也都是可迭代的。例如字符串也是可迭代的。
Iterator 就是针对那么多可迭代的数据结构中是一种统一的接口机制,只要部署了这个接口,就可以被依次遍历处理。
Iterator 的遍历过程是这样的:
{value:any,done:boolean}
手写 Iterator
下面我们通过一个例子快速了解核心概念。
需要知道的是,对象默认是没有 Iterator 接口的,所以它不能被 for..of 循环。这里我们手动给它设置 Iterator 接口。
如果能让上面的
range
对象通过for..of
循环打印出0、1、2、3、4、5。这就代表 iterator 接口部署成功了1.首先我们要给它设置一个属性,这个属性只能通过Symbol.iterator访问,这个属性保存一个函数。
这个
Symbol.iterator
是部署的开始,当 for..of 开始循环时,会调用Symbol.iterator
函数2.
Symbol.iterator
函数会返回一个对象,内部有一个 next 方法,并返回{value:xxx,done:boolean}
这样的对象。3.打印信息
会依次打出0-5的数,
Iterator
接口部署成功了。小结
如果需要部署 Iterator 接口,我们需要手动添加 Symbol.Iterator属性。
这个属性保存着一个函数,当 for..of 开始时,就会调用该函数,并返回Iterator 对象,此时指针初始化。
Iterator对象内部保存着一个 next 函数,for..of 的每次循环都会调用到Iterator对象中的next 函数,所以这时候的 this 指向 Iterator 对象。
next函数会返回
{value:xx,done:boolean}
的数据结构。 当 done 为 true 时,循环停止。for..of
循环每次都会取返回结果的value
属性内置 Iterator
数组跟字符串内置了 Iterator 接口,所以我们可以直接使用 for..of来循环,比如下面的字符串
下面我们直接获取它的
Symbol.iterator
属性,来看看到底发生了什么。我们已经知道这个属性保存着一个函数,这个函数会返回 Iterator 对象,所以我们直接调用拿到这个对象。
这个对象内部会执行 next 方法,返回
{value:xx,done:boolean}
对象现在我们得出一个结论:可迭代对象就是内部部署了 Iterator接口的对象,这个部署 Iterator 接口的标志是内部有
[Symbol.iterator]
属性。我们可以通过浏览器打印出来看一下,比如例子中的
strings
的原型上就有[Symbol.iterator]
属性,它是一个函数。我们直接调用这个方法,然后看看内部到底是个啥
可以看到返回的StringIterator 的原型上有个 next 方法。
伪数组问题
可迭代对象的概念就是实现
[Symbol.iterator]
方法的对象伪数组和数组一样,本质上是个对象,但是数组有数组原型(
Array.prototype
),而伪数组没有数组原型。通过上面的截图我们知道
[Symbol.iterator]
会部署在原型上,比如数组原型、字符串原型里就有部署这个属性。对象以及其原型是没有部署
Iterator
接口的。伪数组既然没有数组的原型,那就不一定有 Iterator 接口。比如下面是一个伪数组
它的原型直接连接到
Object.prototype
上,所以它没有数组的共用方法。比如push
,pop
等等。如果希望实现,那可以采用
Array.from
。这样这个伪数组就具备 Iterator 接口了。
有没有一种伪数组虽然没有数组的原型,但是却默认部署 Iterator 接口的呢?
有的,任何可以被扩展运算符变成数组的伪数组都有
Iterator
接口。比如
arguments
虽然没有数组的原型,但是却具有[Symbol.iterator]
接口扩展运算符把伪数组变成数组?
也许你会认为扩展运算符能把所有伪数组变成数组,不过这只对了一半。
扩展运算符只能把已经具备 Iterator 接口的数据变成数组。不信我们看
结论就是只要你部署了Iterator 接口,才能用扩展运算符转化为数组。可不要弄反顺序噢。
总结
Iterator 是一个接口,具备 Iterator 接口的特点是内部有
[Symbol.iterator]
属性。这个属性保存着一个会返回 Iterator 对象的函数。Iterator对象内部具备 next 方法,会返回键名为 done 和 value 的对象。
for..of 遍历器为部署了 Iterator 接口的数据结构而生,当使用 for..of 遍历时,会首先调用
[Symbol.iterator]
方法,生成Iterator
对象,每次循环都会调用这个对象内部的 next 方法。有一些伪数组没有部署Iterator 接口,所以不能被扩展运算符转化为数组。这时候需要采用
Array.from
方法。Symbol.iterator 方法会被 for..of 自动调用,但我们也可以直接调用它。
内置的可迭代对象例如字符串和数组,都实现了 Symbol.iterator。
The text was updated successfully, but these errors were encountered: