1.什么是for-of循环
对于如下一个数组,便利其中的值,方法有哪些?
var arr = ['a', 'b', 'c'];
首先想到的就是for循环
for(var i = 0; i++; i<arr.length){
console.log(arr[i])
}
如果了解es5,还可以用for-in
for(var i in arr){
console.log(arr[i])
}
然而还有另外一种遍历方法for-of
for(var ch of arr){
console.log(ch)
}
使用for-of时,ch不是arr的索引,而是其中的value值
for-of相比for-in的独特之处:
let arr = 'abc'
for(var char of arr){
console.log(char)
}
//输出a,b,c
但是for-in是无能为力的。for-of不仅可以对数组和字符串遍历,还可以适用于集合:Map,Set,NodeList。NodeList是DOM对象集合。
2、迭代器(Iterator)实现原理
var obj = {0:'abc',1:'def'}
for(var value of obj){
console.log(value)
}
运行后会报错,表明字面量对象是不可遍历的。如果要像Array,String等对象一样支持for-of遍历,可以像Array,String等对象一样,在他们的原型上,实现迭代器(Iterator)的接口。
实现迭代器的接口,需要在这个对象上实现[Symbol,iterator]属性方法。
var obj = {
0: 'abc',
1: 'def',
//实现[Symbol.iterator]属性方法
[Symbol.iterator]:function() {
const self = this
let index = 0
return {
next: function(){//实现next()
if(index<2){
return {//遍历中
value: self[index++],
done:false//表示遍历没有结束,done设置为fasle
}
}else{
return {
value: undefined,//结束后,返回undefined
done: true//表示遍历结束,done设置为true
}
}
}
}
}
}
for(var val of obj){
console.log(val)
}
此时正确的遍历了obj,[Symbol.iterator]属性函数体,返回了next方法,next方法中遍历了此obj的属性对象,并返回字面量对象{value:xxx,done:xxx}。遍历过程中value表示对应属性值,且done设置false;当遍历结束后,value返回undefined,且done设置为true。
var it = obj[Symbol.iterator]()
console.log(it.next())//{value: 'abc', done: false}
console.log(it.next())//{value: 'def', done: false}
console.log(it.next())//{value: undefined, done: true}
这就是for-of的原理,每次遍历都会调用对象的[Symbol.iterator]属性的next方法,当返回{value: undefined,done: true}后,表示遍历结束。随意任何对象要变成可遍历对象,只需要实现[Symbol.iterator]属性方法,定义其中的next方法即可。
3、break,continue
for-of对于for-in的优点就是它支持这些语句。
let arr = 'abc'
for(var char of arr){
console.log(char) //'a'
break
}
仅输出了'a'就跳出的循环。
我们将上面的obj修改一下,使其支持这些语句
var obj = {
0: 'abc',
1: 'def',
//实现[Symbol.iterator]属性方法
[Symbol.iterator]:function() {
const self = this
let index = 0
return {
next: function(){// 实现next()
if(index<2){
return {//遍历中
value: self[index++],
done:false//表示遍历没有结束,done设置为fasle
}
}else{
return {
value: undefined,//结束后,返回undefined
done: true//表示遍历结束,done设置为true
}
}
},
return: function(){//增加return,支持break,continue
return {done:false}
}
}
}
}
for(var val of obj){
console.log(val)
break
}
网友评论