参考:
for in 和 for of 相对于大家肯定都不陌生,都是用来遍历属性的没错。那么先看下面的一个例子:
例1:
以上是遍历对象,下面再看一个遍历数组的例子。
var arr = [1,3,5]
//for-in循环
for(let i in arr) {
console.log(i);
//0
//1
//2
}
//for-of循环
for(let i of arr){
console.log(i);
//1
//3
//5
}
以上代码是对一个数组进行遍历, for in 返回的值为 0、1、2,这是数组的下标
而 for of 返回的是1,3,5
例2
var arr = [1,3,5]
arr.name = 'single'
for(let i in arr) {
console.log(i);
//0
//1
//2
//name
}
for(let i of arr){
console.log(i);
//1
//3
//5
}
for in 循环可以遍历出 name 这个键名
例3
var obj = {
name:'张三',
age: 18,
sex: "男"
}
for(let i in obj) {
console.log(i);
//name
//age
//sex
}
for(let i of obj){
console.log(i);
//TypeError: obj is not iterable at Object.
}
例4
var obj = {
name:'张三',
age: 18,
sex: "男"
}
obj.score = 97.5
for(let i in obj) {
console.log(i);
//name
//age
//sex
//score
}
for(let i of obj){
console.log(i);
//TypeError: obj is not iterable at Object.
}
以上代码通过 for in 和 for of 对一个obj对象进行遍历,for in 正常的获取了对象的 key值,而 for of却报错了。
结合上面的两个例子,分析得出:
for ... in 循环返回的值都是数据结构的 键名。如——例1,例3
遍历对象返回的对象的key值,遍历数组返回的数组的下标(key)。
for ... in 循环不仅可以遍历数字键名,还会遍历原型上的值和手动添加的其他键。如——例2
特别情况下, for ... in 循环会以任意的顺序遍历键名
for of 循环用来获取一对键值对中的键值。如——例1,例3
一个数据结构只要部署了 Symbol.iterator 属性, 就被视为具有 iterator接口, 就可以使用 for of循环。
例3这个对象,没有 Symbol.iterator这个属性,所以使用 for of会报 obj is not iterable
哪些数据结构部署了 Symbol.iteratoer属性了呢?
只要有 iterator 接口的数据结构,都可以使用 for of循环。
原生具备 Iterator 接口的数据结构如下。
以上这些都可以直接使用 for of 循环。 凡是部署了 iterator 接口的数据结构也都可以使用数组的 扩展运算符(...)、和解构赋值等操作。
我也想让对象可以使用 for of循环怎么办?
方法1:使用 Object.keys() 获取对象的 key值集合后,再使用 for of
以例1为例
var obj = {
name:'张三',
age: 18,
sex: "男"
}
for(let i of Object.keys(obj)){
console.log(i);
//name
//age
//sex
}
方法2:也可以给一个对象部署 Symbol.iterator属性
let obj={
name:'张三',
age: 18,
sex: "男"
}
function* objectEntry(obj) {
let newObj = Reflect.ownKeys(obj)
for(let i of newObj) {
yield [i,obj[i]]
}
}
for(let i of objectEntry((obj))) {
console.log(i);
}
function* objectEntries() {
// let propKeys = Object.keys(this);
let propKeys = Reflect.ownKeys(this);
for (let i of propKeys) {
yield [i, this[i]];
}
}
let obj={
name:'张三',
age: 18,
sex: "男"
}
obj[Symbol.iterator] = objectEntries
for(let i of obj) {
console.log(i);
}
注:Reflect.ownKeys
方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames
与Object.getOwnPropertySymbols
之和。