【问题标题】:JS function given to Array.prototype seen as array property赋予 Array.prototype 的 JS 函数被视为数组属性
【发布时间】:2011-10-11 07:35:29
【问题描述】:
Array.prototype.testi = function() {console.log('hep');}
var b = new Array();

b.push(1, 5, 'b', 'c');

for (var i in b) {
    console.log(b[i]);
}

这将登录(在 chrome 中)

1
2
b
c
function () {console.log('hep');}

http://jsfiddle.net/marqs/6VVka/1/中的实时示例

我的问题是,为什么列表中显示的函数,即使它被赋予了数组原型?

这对扩展未使用的浏览器功能有影响(例如,如果使用 array in 等,IE 扩展的 Array.filter 的行为会有所不同)。

编辑: 澄清一下,我无法访问执行 for-in 循环的代码,因为它是一个外部库。因此,问题的提出,更多的是关于“为什么会这样”而不是如何解决这个问题。

【问题讨论】:

    标签: javascript definition function-prototypes


    【解决方案1】:

    JavaScript 对象是属性的集合。在这些属性中,有描述属性的属性。您在这里看到的主要属性是 [[Enumerable]] 属性,它是一种元属性,扩展到 JavaScript 中的大多数默认对象,例如 Array 和 Object。 ECMAScript 5 定义了一种添加非 [[Enumerable]] 对象的方法,但浏览器可能不广泛支持。

    防止枚举不需要的对象属性的一种方法是检查对象属性是否具有称为[[GetOwnProperty]] 的内部属性方法。这确保了该属性是直接在对象上调用的,而不是沿原型链的某个地方继承的。

    var arr = ['a','b','c'], indexes = [];
    Array.prototype.each = function() {/*blah*/}; 
    
    for (var index in arr) {
        if (arr.hasOwnProperty(index)) {
        indexes.push(index);
        }
    }
    
    indexes; //["0", "1", "2"]
    

    来源:http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/

    【讨论】:

    • 不幸的是,我无法更改代码来执行此操作,因为它是从另一台服务器加载的库。所以我主要感兴趣的是为什么会发生问题以及我可以做些什么来避免它发生......这意味着在这种情况下我无法扩展 Array.prototype。
    • Marcus - 你可以使用 obj.hasOwnProperty(var) 方法。在此处进行演示:jsfiddle.net/6VVka/5 如果这对您不起作用,请与我联系。
    • 我了解它的工作原理并解决了根本问题。我的意思是,问题出在我正在使用的开源组件(openLayers)中。如果我在 Openlayers 中解决了这个问题(并且它广泛使用了 for-in),我将被我的自定义绑定到那个版本。因此,出于实际原因,我只需要接受在当前项目中我无法扩展 Array-prototype 的事实。但如果我自己使用 var-in,我一定会使用 obj.hasOwnProperty-check...
    • @Marcus 你可以尝试使用delete Array.prototype.testi在Array原型中删除它
    【解决方案2】:

    for-in 循环将遍历对象的所有继承属性以及它自己的属性。 Ecmascript 5 中有一种方法可以从枚举中隐藏您的属性,请参阅Ecmascript 5 Objects and Properties,但这在 IE 中不起作用。迭代数组的推荐方法是使用普通的 for 循环:

    for (var i = 0, len = b.length; i < len; i++)
        console.log(b[i])
    

    这也将比 for-in 循环具有更好的性能,因为它避免了通过原型链在对象上查找属性。 len 变量用于缓存数组的长度,以避免在循环的每次迭代中查找它。如果你想变得圆滑,你可以:

    for (var i = b.length; i--;)
        console.log(b[i])
    

    这会反向迭代数组,并避免额外的len 变量。

    【讨论】:

    • 感谢您的回答。我碰到这个的原因是我们正在使用一个外部库来进行 for-in 迭代。
    【解决方案3】:

    您在对象原型上添加的任何东西都会出现在该对象的所有实例中。这就是我们可以在 javascript 中扩展对象的方式。

    请参考:http://phrogz.net/js/classes/ExtendingJavaScriptObjectsAndClasses.html

    【讨论】:

      【解决方案4】:

      Douglas Crockford 显然也写过同样的问题。

      缺陷是for in语句,它可以枚举键 存储在对象中,产生对象的所有键 原型链,而不仅仅是对象本身的键。这导致 继承的方法出现在枚举中,这是不好的。如果会 如果 JavaScript 不包含这个缺陷会更好,但是 幸运的是,我们可以围绕它进行编程。

      http://yuiblog.com/blog/2006/09/26/for-in-intrigue/

      【讨论】:

        猜你喜欢
        • 2012-12-03
        • 1970-01-01
        • 2011-11-11
        • 1970-01-01
        • 2020-11-11
        • 2020-08-10
        • 1970-01-01
        • 2021-04-14
        • 1970-01-01
        相关资源
        最近更新 更多