for in与for of 的区别

138 阅读3分钟

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]}`);
}

uTools_1690944560133.png

这段代码在执行完后,确实打印了自己的对象上的属性,也打印了原型上的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]);
}

uTools_1690945408192.png 我们发现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);

uTools_1690955950922.png 我们发现里面的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) {
}

uTools_1690956370518.png

我们发现数组可以被for of 变量,对象不可以,于是我们按照上面的规则来查看原型上面

uTools_1690956495137.png

uTools_1690956515035.png 果然,数组的原型上存在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);
}

uTools_1690957299333.png

这里代码的编写是用的迭代器的知识,可以自行学习