1.遍历数组
for in,for of都可以遍历数组的,for in 里面的key(定义的一个变量)是数组的下标,而for of里面的key是数组每个下标对应的值
let arr = ["a","b"]; for (let key in arr) { console.log(key);//0,1 console.log(arr[key]);//a b } for (let key of arr) { console.log(key);//a,b console.log(arr[key]);//undefined undefined }
2.遍历对象
for in可以遍历对象,但是for of不行(如果对象本身定义了迭代器的话就可以遍历)
let obj = { a:1, b:2, c:3, } for(let key in obj){ console.log(key);//a b c console.log(obj[key]);//1 2 3 } for(let key of obj){ console.log(key);//Uncaught TypeError: obj is not iterable console.log(obj[key]);//Uncaught TypeError: obj is not iterable }
3.for of遍历对象的方法
首先我们先来了解一个叫作@@iterator的家伙,这个家伙是数组内置的,我们使用ES6的Symbol.iterator获取对象的@@iterator内部属性,它主要是用来返回一个迭代器对象的函数。它的next()方法会返回一个形为{value:....,done:...}的值,value是当前的遍历的值,done是一个布尔值,表示是否还有可以遍历的值。
var arr = [1,2,3]; var it = arr[Symbol.iterator](); console.log(it.next());//{value: 1, done: false} console.log(it.next());//{value: 2, done: false} console.log(it.next());//{value: 2, done: false} console.log(it.next());//{value: undefined, done: true}
对象是没有这个家伙的,但是我们可以给想要遍历的对象定义个@@iterator,具体如下:
let obj ={ a:1, b:2, c:3, } Object.defineProperty(obj,Symbol.iterator,{ enumerable:false, writable:false, configurable:true, value:function(){ var o = this;//obj var idx = 0;//下标等下用来遍历值 var ks = Object.keys(o);//返回一个包含所有属性名的数组 return { next:function(){ return{ value:o[ks[idx++]], done:(idx>ks.length)//如果idx大于kx的长度表明已经遍历完毕,没有再遍历的了 }; } }; } }); //手动遍历obj var it = obj[Symbol.iterator](); console.log(it.next());//{value: 1, done: false} console.log(it.next());//{value: 2, done: false} console.log(it.next());//{value: 3, done: false} console.log(it.next());//{value: undefined, done: true} for(let key of obj){ console.log(key);//1 2 3 console.log(obj[key])//undefined undefined undefined }
这样我们就可以实现for of的对象遍历了,这时候,我再想一个问题为什么for of不能用来遍历对象了?
其实,简单来说就是为了避免影响未来的对象的类型。