for in
和 for of
是js中常用的遍历方法。但是两者有什么区别呢?
今天我们就来讨论下两者的区别。
遍历数组
-
for in
是ES5的语法标准,而for of
则是ES6语法标准。
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
}
通过上述代码我们可以发现for in
遍历的是下标,而for of
遍历的是属性值
而且。for in
所遍历的下标是Strign类型而不是Number类型。
-
for in
遍历时可以遍历到当前数组的所有属性名和方法名。包括其原型链上定义的属性名和方法名。如下代码:
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
遍历时则不会遍历原型链上的属性和方法且不会遍历定义在数组上的属性和方法。
代码如下:
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'
}
遍历对象
- 使用
for in
遍历对象会遍历对象原型链的方法名和属性名,for in
循环实际是为循环可枚举(enumerable)对象而设计的
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
遍历对象则会报错
for(let i of obj){
console.log(i)
}
// error Uncaught TypeError: obj is not iterable
这是为什么呢?
这是因为能够被for of
正常遍历的数据类型都需要实现一个遍历器Iterator。而数组、字符串、Set、Map结构,早就内置好了Iterator(迭代器),它们的原型中都有一个Symbol.iterator
方法,而Object对象并没有实现这个接口,使得它无法被for of
遍历。
我们可以通过为Object实现一个Iterator来使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)
}
这样对象就可以使用for of
正确遍历啦!