JS的for in

616 阅读1分钟

之所以会探索for-in到底是怎么工作的,是因为我在使用for-in时遇到了如下问题:

let obj = {
    name: 'fan';
}
for (let key in obj) {
    console.log(key);
}

以上代码的输出结果是 "name",但我以前学的是for-in会遍历本对象以及原型链上所有对象的属性名,而这里的obj明显是继承自Object的,也就是应该会遍历Object.prototype中的属性,但事实是没有。

但是,我自己实现的继承,却能访问原型链上的属性:

function Father() {
  this.age = 20;
}
function Son() {
  this.school = 'whut';
}
// 实现继承
Son.prototype = new Father();
Son.prototype.constructor = Son;
// 给父构造函数原型对象加个属性
Father.prototype.year = 2021;
let son = new Son();
for (let e in son) {
  console.log(e);
}

以上的输出结果是:school age constructor year,显然,for-in又确确实实访问了原型链上对象的属性。

于是,仔细阅读for-in的定义:以随机的顺序遍历一个对象的除Symbol以外的可枚举属性。

关键问题就是属性是否可遍历(Enumerable),它只能访问Enumerable为true的属性,而Object.prototype中的属性都是不可遍历的,当然就没办法访问Object.prototype上的属性了。自己实现的继承能访问是因为Enumerable为true:

1.png 只要我给自己实现的继承加上不可遍历,一样for-in也不能访问了:

Object.defineProperty(Father.prototype, 'year', {
  enumerable: false
});

以上代码的year属性就无法通过for-in obj来访问到。