for in
和 for of
是js中常用的遍歷方法滞项。但是兩者有什么區(qū)別呢盏缤?
今天我們就來(lái)討論下兩者的區(qū)別。
遍歷數(shù)組
-
for in
是ES5的語(yǔ)法標(biāo)準(zhǔn)蓖扑,而for of
則是ES6語(yǔ)法標(biāo)準(zhǔn)。
const arr = ['a', 'b', 'c']
for(let i in arr){
console.log(i)
// '0', '1', '2'
}
for(let i of arr){
console.log(i)
// a, b, c
}
通過(guò)上述代碼我們可以發(fā)現(xiàn)for in
遍歷的是下標(biāo)台舱,而for of
遍歷的是屬性值
而且律杠。for in
所遍歷的下標(biāo)是Strign類(lèi)型而不是Number類(lèi)型。
-
for in
遍歷時(shí)可以遍歷到當(dāng)前數(shù)組的所有屬性名和方法名竞惋。包括其原型鏈上定義的屬性名和方法名柜去。如下代碼:
const arr = ['a', 'b', 'c']
arr.name = 'arr'
arr.getName = function(){
return this.name
}
arr.__proto__.constructor.prototype.sayHello = function(){
return 'hello'
}
arr.__proto__.constructor.prototype.parentName = 'say uncle'
for(let i in arr){
if(arr.hasOwnProperty(i)){
console.log('ownProperty',i)
// '0', '1', '2', 'name', 'getName'
}else{
console.log('not ownProperty',i)
// 'sayHello', 'parentName'
}
}
而使用for of
遍歷時(shí)則不會(huì)遍歷原型鏈上的屬性和方法且不會(huì)遍歷定義在數(shù)組上的屬性和方法。
代碼如下:
const arr = ['a', 'b', 'c']
arr.name = 'arr'
arr.getName = function(){
return this.name
}
arr.__proto__.constructor.prototype.sayHello = function(){
return 'hello'
}
arr.__proto__.constructor.prototype.parentName = 'say uncle'
for(let i of arr){
console.log(i)
// 'a', 'b', 'c'
}
遍歷對(duì)象
- 使用
for in
遍歷對(duì)象會(huì)遍歷對(duì)象原型鏈的方法名和屬性名,for in
循環(huán)實(shí)際是為循環(huán)可枚舉(enumerable)對(duì)象而設(shè)計(jì)的
const obj = {
name:'uncle',
gender: 'male',
age:12,
}
obj.hobby = 'coding'
obj.getName = function(){
return this.name;
}
obj.__proto__.constructor.prototype.sayHello = function(){
return "hello"
}
for(let i in obj){
if(obj.hasOwnProperty(i)){
console.log('ownProperty',i)
// name, gender, age, hobby, getName
}else{
console.log('not ownProperty',i)
// sayHello
}
}
而使用 for of
遍歷對(duì)象則會(huì)報(bào)錯(cuò)
for(let i of obj){
console.log(i)
}
// error Uncaught TypeError: obj is not iterable
這是為什么呢拆宛?
這是因?yàn)槟軌虮?code>for of正常遍歷的數(shù)據(jù)類(lèi)型都需要實(shí)現(xiàn)一個(gè)遍歷器Iterator嗓奢。而數(shù)組、字符串浑厚、Set股耽、Map結(jié)構(gòu),早就內(nèi)置好了Iterator(迭代器)钳幅,它們的原型中都有一個(gè)Symbol.iterator
方法物蝙,而Object對(duì)象并沒(méi)有實(shí)現(xiàn)這個(gè)接口,使得它無(wú)法被for of
遍歷敢艰。
我們可以通過(guò)為Object實(shí)現(xiàn)一個(gè)Iterator來(lái)使Object可以使用正常for of
遍歷
Object.prototype[Symbol.iterator] = function() {
let _this = this
let index = 0
let length = Object.keys(_this).length
return {
next:() => {
let value = _this[Object.keys(_this)[index]]
let done = (index >= length)
index++
return {value,done}
}
}
}
for(let i of obj){
console.log(i)
}
這樣對(duì)象就可以使用for of
正確遍歷啦诬乞!