迭代器和生成器

Interator对象

1、Symbol.iterator属性 为每一个对象定义了默认的迭代器。该迭代器可以被 for...of 循环使用。

【终于明白了js的内置方法】属性指向一个方法,以数组来讲,大部分属性名和方法名是相同的,但也有例外,比如:constructor属性指向的是Array方法,Symbol.iterator属性指向的values方法

数组原型上的构造函数constructor,指向Array方法,所以可以这么调用Array方法:

2、可以调用for of的原因

(1)字符串:

String.prototype上有Symbol.iterator属性,该属性对应[Symbol.iterator]方法

let str = "abc";
console.log(str[Symbol.iterator]())  StringIterator {}
let strIter = str[Symbol.iterator]()
console.log(strIter.next().value);   a
console.log(str = "123")             123
console.log(strIter.next().value);   b

我们知道字符串的原型上是有 Symbol.iterator属性的,即可以通过for of迭代每一项。

我们执行Symbol.iterator属性对应的方法时,获取Iterator对象,比如:字符串的Iterator对象是StringIterator。该对象是可以调用next方法的,因为只有Iterator对象可以调用next方法。

StringIterator对象上的原型上还有Symbol.iterator属性,所以StringIterator对象还可以调用for of进行迭代。

 需要注意:str是原始值,当获取到StringIterator对象后,StringIterator对象拿到的是内存中“abc”的地址,当修改str的值的时候,str不再指向“abc”的内存,而是指向“123”的内存,但这不影响StringIterator对象,StringIterator对象依旧会指向“abc”。

但是需要注意:引用值改变后,对应的Iterator对象也会改变。

需要注意的是:Iterator对象通过for of 或next方法都是同样进行迭代,都会修改Iterator对象内的指针,比如:StringIterator对象先执行一次next方法,使得指针后移一位,再进行for of迭代的时候,只会打印 b  和 c的值。

let str = "abc";
let strIter = str[Symbol.iterator]()
strIter.next();
for(let value of strIter) {
    console.log(value); b  c
}

 展开运算符和解构赋值也是调用的iterator接口:

let str = "abc";
console.log([...str])  ["a", "b", "c"]

(2)数组:

Array.prototype上有Symbol.iterator属性,该属性对应的是values方法,和values属性的方法一致

 因为数组的原型上有Symbol.iterator属性,即可以通过for of进行迭代每项的值,比如:

let arr = ["a","b","c"];
for(let value of arr) {
    console.log(value);    a  b   c
}

 我们发现数组原型上的values属性和Symbol.iterator属性都指向values方法,values() 方法返回一个新的 Array Iterator 对象,即Array Iterator {} ,该对象也是Iterator对象,可以调用next方法以及进行for of迭代每项的值。

let arr = ["a","b","c"];
let arrIter = arr.values() || arr[Symbol.iterator]();  Array Iterator {} 
arrInter.next();    a
arr[1] = 2;
for (let value of arrIter) {
    console.log(value);        2   c
}

特别注意:修改原数组会修改对应的Iterator对象;

(3)arguments对象

arguments对象上有Symbol.iterator属性,与数组的情况基本上相同

function arg() {
    for (let value of arguments){
        console.log(value);  a  b  c
    }
    let argIter = arguments[Symbol.iterator]();  Array Iterator {}
    argIter.next(); a 
    for(let value of argIter){
        console.log(value);  b c
    }
}
arg("a","b","c")

(4)Set对象

跟数组几乎一样的

let set = new Set();
set.add("a").add("b").add("c");
for(let value of set){
    console.log(value); a b c
}
let setIter = set.values() || set[Symbol.iterator]();  SetIterator {"a", "b", "c"}
console.log(setIter);
setIter.next();  a
set.delete("b")
for(let value of setIter){
    console.log(value);  c
}

(5)Map对象

 Map对象调用entries方法或[Symbol.iterator]方法,都是调用的entries方法,得到Map对象对应的的Iterator对象。

我们知道Map对象的keys和values也会得到Interator对象,但是内容却和Map对象不一样。而entries方法得到的内容是和原本的Map对象内容一致。

所以Map对象的[Symbol.iterator]属性,调用entries方法,得到对应MapIterator对象。

思考:为什么Set对象的[Symbol.iterator]属性调用的是Set对象的values方法?!

let map = new Map();
map.set("1","a").set(true,"b").set([2,3],"c"); Map(3) {"1" => "a", true => "b", Array(2) => "c"}
console.log(map);
for(let value of map){
    console.log(value);  ["1", "a"]   [true, "b"]  [[2, 3], "c"]
}
let mapIter = map[Symbol.iterator]() || map.valuse();  MapIterator {"1" => "a", true => "b", Array(2) => "c"}

mapIter.next();
map.set(true,"d");
for(let value of mapIter){
    console.log(value)   [true, "d"]   [[2, 3], "c"]
}

类型数组:TypeArray

与数组一模一样!

let uint8 = new Uint8Array(3);
uint8[0] = 1;
uint8[1] = 2;
uint8[2] = 3;
console.log(uint8);   //Uint8Array(3) [1, 2, 3]
for(let value of uint8){
    console.log(value);  1  2  3
}
let typeArrIter = uint8[Symbol.iterator](); //Array Iterator {}
console.log(typeArrIter);
uint8[1] = 10;
typeArrIter.next();
for(let value of typeArrIter){
    console.log(value);  10  3
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值