在对数组或对象进行遍历时,我们经常会使用到两种方法:for-in
和 for-of
,那么这两种方法之间的区别是什么呢?
for-in
for-in
是一种严格的迭代语句,用于枚举对象的非符号键属性
语法:
for(property in expression) statement
例子:
for(const propName in window){
document.write(propName+"<br>")
}
这个例子使用for-in
循环显示了DOM对象window的所有属性。每次执行循环都会给变量propName
赋予一个window
对象的属性作为值,直到window
的所有属性都被枚举一遍。
ECMAScript
中对象的属性是无序的,因此for-in
循环不能保证返回对象的顺序。换句话说,所有可枚举的属性都会返回一遍,但返回的顺序可能会因浏览器而变。
如果for-in
循环要迭代的变量是null
或undefined
,则不执行循环体。
EN…,以上文字摘抄自红宝书第四版75-76页,但是理解上还是存在一定的难度。
for-in
循环只遍历可枚举属性。像 Array
和Object
使用内置构造函数所创建的对象都会继承自Object.prototype
和String.prototype
的不可枚举属性,例如String
的indexOf()
方法或 Object
的toString()
方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。
下面使用for-in
对对象和数组遍历:
let obj={
name:"张三丰",
age:108,
job:"programmer"
}
for(let i in obj){
console.log("i:"+i,","+obj[i]);
}
let arr = [12,23,34]
for(let i in arr){
console.log("i:"+i,","+arr[i]);
}
我们发现,使用for-in
进行遍历时,i
为对象的key
,数组的index
。
数组索引只是具有整数名称的枚举属性,并且与通过对象属性相同,因此不能保证for-in
以某种固定的顺序返回索引,所以不推荐使用for-in
遍历数组。
在上面代码的基础上,在arr数组上增加一个自定义属性,再次遍历,查看结果
let arr = [12,23,34]
arr.name = "张三丰";
for(let i in arr){
console.log("i:"+i,","+arr[i]);
}
for-in
不仅会遍历数组中的元素,还会遍历自定义属性
for-of
for-of
语句是一种严格的迭代语句,用于遍历可迭代对象的元素。
语法:
for(property of expression) statement
下面是示例:
for(const el of [2,4,6,8]){
document.write(el+"<br>")
}
在这个例子中,我们使用for-of
语句显示了一个包含4个元素的数组中的所有元素。循环会一直持续到将所有元素都迭代完。
for-of
循环会按照可迭代对象的next()
方法产生值的顺序迭代元素。
如果尝试迭代的变量不支持迭代,则for-of
语句会报出错误
以上文字摘抄自红宝书第四版76页
for-of
语句在可迭代对象(包括 Array
,Map
,Set
,String
,TypedArray
,arguments
对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
let obj={
name:"张三丰",
age:108,
job:"programmer"
}
for(let i of obj){
console.log("i:"+i,","+obj[i]); //obj is not iterable
}
let arr = [12,23,34]
arr.name = "张三丰";
for(let i of arr){
console.log("i:"+i,","+arr[i]);
}
使用for-of
对对象进行遍历时报错,对数组进行遍历时,i
直接时数组每一项的值。
为arr增加自定义属性,查看效果
let arr = [12,23,34]
arr.name = "张三丰";
for(let i of arr){
console.log("i:"+i,","+arr[i]);
}
for-of
没有对数组的自定义属性进行遍历。
区别
- 遍历对象时推荐使用
for-in
,其中i
为对象的key
。使用for-of
会报错。 - 遍历数组时推荐使用
for-of
,其中i
为数组每一项的值。使用for-in
则不能保证遍历顺序且会遍历出自定义属性。 for-in
是ES5
特性,fro-of
是ES6
特性,注意兼容- 如果要使用
for-of
遍历普遍对象,需要配合Object.keys()
一起使用。