for in与for of一般在使用的时候,就是for in用于对象,for of用于数组,但是这到底是怎么回事,或者还有别的用法吗,这篇文章来深入的学习一下。
for in
首先我们来看mdn的官方介绍
for...in语句以任意顺序迭代一个对象的除[Symbol]以外的可枚举属性,包括继承的可枚举属性。
symbol是es6推出的新的数据类型,这里就不多介绍了,大家自己去学习即可
这里主要来看看可枚举属性,这里用一段代码来举例
const obj = new Object();
Object.prototype.sex = "male";
obj.name = "111";
obj.age = 100;
for (const prop in obj) {
console.log(`${prop}->${obj[prop]}`);
}
这段代码在执行完后,确实打印了自己的对象上的属性,也打印了原型上的sex,但是Object原型还有那么多方法,为什么都没有打印出来,这里就要引出我们的关键知识属性描述符
Object.defineProperty(属性描述符)
之前对于对象的属性,我们都只有赋值,删除,覆盖。而通过属性描述符,给了我们更多的操控属性的方法。因本文在讲述for in所以,对于属性描述符,只讲述需要的部分
let obj = { name: "sdy", age: 100 };
Object.defineProperty(obj, "name", {
enumerable: false, //表示该属性是否可枚举,false不可以,true可以枚举
});
for (const prop in obj) {
console.log(obj[prop]);
}
我们发现name属性没有被打印出来,没错就是通过属性描述符,来控制这个属性到底是不是可枚举属性
在最开始的例子里面,我们使用for in打印不出来,Object原型自带的方法,这里我们来检测一下,Object.getOwnPropertyDescriptor可以查看该元素的属性描述符的内容
let res1 = Object.getOwnPropertyDescriptor(Object.prototype, "constructor");
let res2 = Object.getOwnPropertyDescriptor(Object.prototype, "toString");
console.log(res1);
console.log(res2);
我们发现里面的enumerable都是false,这就是我们不能枚举到原型链上的属性的原因
for of
mdn官方介绍, for...of语句 可迭代对象上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句
这里的关键是可迭代对象,但到底什么是可迭代对象那。如果我们能在自身或者原型链上找到Symbol(Symbol.iterator)那么这个对象就是可迭代的
const obj = { name: 1 };
const arr = [1, 2, 3];
for (const prop of arr) {
console.log(prop);
}
for (const prop of obj) {
}
我们发现数组可以被for of 变量,对象不可以,于是我们按照上面的规则来查看原型上面
果然,数组的原型上存在Symbol(Symbol.iterator),所以他能被for of遍历。
那么按照这个规则给对象上也来一个,那么对象是不是也能被for of遍历了的,确实是这样的。
const obj = {
name: "sdy",
age: 100,
sex: "male",
[Symbol.iterator]: function () {
const keys = Object.keys(this);
let i = 0;
return {
next() {
let res = {
value: obj[keys[i]],
done: i >= keys.length,
};
i++;
return res;
},
};
},
};
for (const prop of obj) {
console.log(prop);
}
这里代码的编写是用的迭代器的知识,可以自行学习