“ For In”可以遍历数组(值/属性/函数)。
let arr = [1,2,3,4];
arr.__proto__.con = function(){console.log('from array');}
for(let item in arr){
console.log(item);
}
结果将是:
1,2,3,4,con
为什么不打印“ toString” /“ split”之类的本机功能? 有什么区别?
在我看来,它们(con
和toString
)都属于Array的原型。
答案 0 :(得分:3)
for...in
语句...
迭代对象的所有非符号可枚举属性。 (source: MDN)
但是,如果您查看ECMA specification,在项目“数组原型对象的属性” 中,您将看到:
Array原型对象是固有对象%ArrayPrototype%。 Array原型对象是Array奇异对象,并具有为此类对象指定的内部方法。它具有一个length属性,其初始值为0,其属性为{[[Writable]]:true, [[Enumerable]]:false ,[[Configurable]]:false}。
这适用于concat
,filter
,map
,forEach
,sort
,toString
等...
您可以使用Object.getOwnPropertyDescriptor
来检查那些属性。例如:
console.log(Object.getOwnPropertyDescriptor(Array.prototype, "concat"));
最后,要使用{enumerable: false}
设置这些方法,请看一下other answer。
答案 1 :(得分:1)
将方法分配给原型并不重要。默认情况下,任何类型的对象的属性均为enumerable,无论它们是分配给对象的原型还是直接分配给对象:
class MyClass {
constructor() {
this.x = 10;
}
}
let test = new MyClass();
test.y = 20;
for(let item in test) {console.log(item) } // logs x, y
诸如toString
之类的本地方法被设置为不可枚举,原因很明显,您通常不希望遍历它们。通过使用Object.defineProperty
,用户方法或属性也可以设置为不可枚举:
Object.defineProperty(test, "z", {value: 42, enumerable: false})
console.log(test.z); // 42
for(let item in test) {console.log(item)} // still only x, y