第一次写文章,有错误请大佬斧正!
迭代器
1.区分for of和for in
for of是遍历迭代器的,可遍历的对象是一个含有迭代器的对象,一般定义的object是没有自带迭代协议的也就是@@iterator
方法,后面详细讲解此属性,Array、string、map等类型自带有这个属性,也就是本身就是可以被迭代的对象。
for in是遍历可枚举属性的,基本包装类型如Object,Array,Object的原型属性是不可以被枚举的,也就是说必须要自己定义的属性才可以被枚举,是否可以被枚举 通过Object.defineProperty()
方法追加可枚举属性enumerable: true
2.迭代协议
可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,例如,在一个 for..of
结构中,哪些值可以被遍历到。
要成为可迭代对象, 一个对象必须实现 @@iterator
方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator
的属性,可通过常量 Symbol.iterator
访问该属性,比如object[Symbol.iterator]。
当一个对象需要被迭代的时候(比如被置入一个 for...of
循环时),首先,会不带参数调用它的 @@iterator
方法,然后使用此方法返回的迭代器获得要迭代的值。@@iterator
方法必须返回一个迭代器,如果不是使用迭代方法如扩展运算符或者for of
会报错。
3.生成器
生成器对象是由一个 generator function 返回的,并且它符合可迭代协议和迭代器协议,
生成器函数(GeneratorFunction)永远返回一个生成器(Generator).
基本使用方式:
返回一个由
yield
表达式生成的值。返回给定的值并结束生成器。
向生成器抛出一个错误。
function * gen(){
let index = 0;
while(true){
yield index++
}
}
var g = gen()
console.log(g.next())
console.log(g.next())
console.log(g.return())
console.log(g.next())
/*
{ value: 0, done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
*/
4.迭代器、迭代协议和生成器的联系与区别
生成器是一个迭代器,迭代器不一定是生成器,可迭代对象包含了一个迭代协议@@iterator
,同时生成器本身也是一个具有迭代协议的迭代器,可迭代对象可以使用扩展运算符和for...of进行迭代直到done:true
,以下包含这段的具体说明:
迭代器的定义和实现:
只要实现了一个拥有以下语义(semantic)的 next()
方法,一个对象才能成为迭代器:
-
next()
方法是一个无参数函数 -
next()
方法返回一个对象包含done
和value
两个属性 -
done
:如果迭代器可以产生序列中的下一个值,则为false
反之则为true
,value
:迭代器返回的任何 JavaScript 值。由此可见迭代器其实只是实现了一个具有
next()
语义规则的方法,以下也算一个迭代器
function myIterator() {
let index = 0
return {
next: function () {
if(index<5){
return {value:index++,done:false}
}else{
return {value:undefined,done:true}
}
}
};
}
var iter = myIterator()
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
/*{ value: 0, done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }*/
迭代器也就是闭包的一种使用,只不过指定了规则,下面是使用生成器的迭代器:
function * myIterator() {
let index = 0
while(index<5){
yield index++
}
}
var iter = myIterator()
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
/*
{ value: 0, done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }*/
下面是迭代协议的实现和运用:
var Person = {
name:"xiaoxiao",
age:18,
sexy:"girl"
}
console.log([...Person])
//此时可见Person不是一个可迭代对象
/*
console.log([...Person])
^
TypeError: Person is not iterable
*/
--------------------------------------------------------------------------------------
var Person = {
name:"xiaoxiao",
age:18,
sexy:"girl",
} //此时加上迭代协议的Person可以被扩展运算符迭代了
Person[Symbol.iterator] = function(){
let index = 0
return{
next:function(){
if(index<5){
return {value:index++,done:false}
}else{
return {value:undefined,done:true}
}
}
}
}
console.log([...Person])
//[ 0, 1, 2, 3, 4 ]