代码之家  ›  专栏  ›  技术社区  ›  Sudheesh Singanamalla

JS原型方法在循环中访问时的行为不同

  •  0
  • Sudheesh Singanamalla  · 技术社区  · 7 年前

    我使用一个名为 custommethod 如下所示,循环遍历数组中的值。然而,通过索引的循环也会打印 property 通过以下方式扩展 Array.prototype.<method> .

    Array.prototype.custommethod = function() {
        console.log("Hello from Custom Method");
    }
    
    Object.defineProperty(Array.prototype, "anothercustommethod", {
        value: function() {
            console.log("Hello from Another Custom Method");
        }
    });
    

    在阵列中循环

    > x = [1,2]
    [ 1, 2 ]
    
    > for (i in x) { console.log(i); }
    0
    1
    custommethod
    
    • 为什么 anothercustommethod 在这个循环中打印?

    • 正在使用 Object.defineProperty() 更安全的创建方式 Array.prototype ?

    我很好奇 for javascript中的循环实际上是有效的。它是否使用 Object.keys() 内部?如果是,如何打印 自定义方法 在里面 __proto__ 属性,但不是 其他自定义方法 也在里面 __原型__ 所有物

    2 回复  |  直到 7 年前
        1
  •  5
  •   Suren Srapyan    7 年前

    为什么不在这个循环中打印另一个CustomMethod?

    for in 迭代这些属性,其中 enumerable 设置为true。

    Documentation

    可枚举的 当且仅当此属性在 对应对象上属性的枚举。默认为 错误。

    使用时 defineProperty ,也可以传递额外的属性- 可枚举的 . 默认情况下,它设置为false。

    Array.prototype.custommethod = function() {
        console.log("Hello from Custom Method");
    }
    
    Object.defineProperty(Array.prototype, "anothercustommethod", {
        value: function() {
            console.log("Hello from Another Custom Method");
        },
        enumerable: true
    });
    
    const x = [1,2]
    for (i in x) { console.log(i); }

    正在使用对象。defineProperty()创建数组的更安全方法。原型

    没有什么关于安全的。很少尝试更改内置原型

        2
  •  0
  •   xianshenglu    7 年前

    您可以通过以下API检查属性:

    Object.getOwnPropertyDescriptor(Array.prototype,'custommethod');//{value: ƒ, writable: true, enumerable: true, configurable: true}
    Object.getOwnPropertyDescriptor(Array.prototype,'anothercustommethod');//{value: ƒ, writable: false, enumerable: false, configurable: false}
    

    看见第一个得到:可枚举:true,第二个得到:可枚举:false,

    其他值也不同,这是因为当由不同的API设置时,默认设置不同

    实际上,为了更安全,您可以使用以下API:

    对象getOwnPropertyNames

    Object.getOwnPropertyNames(Array.prototype).filter(v=>v.endsWith('custommethod'));//["custommethod", "anothercustommethod"]
    

    如果有符号,您仍然需要

    Object.getOwnPropertySymbols(Array.prototype);//[Symbol(Symbol.iterator), Symbol(Symbol.unscopables)]
    

    对象键的工作方式与中类似,它们不会遍历枚举为false的属性;

    当您尝试使用其他API遍历属性时,应该考虑以下事项