原型中自定义函数和本机函数之间的区别

时间:2019-11-20 04:09:49

标签: javascript

“ 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”之类的本机功能? 有什么区别?

在我看来,它们(contoString)都属于Array的原型。

2 个答案:

答案 0 :(得分:3)

for...in语句...

  

迭代对象的所有非符号可枚举属性。 (source: MDN

但是,如果您查看ECMA specification,在项目“数组原型对象的属性” 中,您将看到:

  

Array原型对象是固有对象%ArrayPrototype%。 Array原型对象是Array奇异对象,并具有为此类对象指定的内部方法。它具有一个length属性,其初始值为0,其属性为{[[Writable]]:true, [[Enumerable]]:false ,[[Configurable]]:false}。

这适用于concatfiltermapforEachsorttoString等...

您可以使用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