给Array.prototype的JS函数看作数组属性

时间:2011-10-11 07:35:30

标签: javascript definition function-prototypes

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/

中的实例

我的问题是,为什么列表中显示的功能,即使它是给予数组原型的?

这对扩展未使用的浏览器功能有影响(例如,如果使用数组输入,IE扩展Array.filter将表现不同)。

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

4 个答案:

答案 0 :(得分:2)

for-in循环将遍历对象的所有继承属性以及它自己的属性。在Ecmascript 5中有一种方法可以隐藏枚举中的属性,请参阅Ecmascript 5 Objects and Properties,但这在IE中不起作用。迭代数组的推荐方法是使用normal 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变量。

答案 1 :(得分:2)

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/

答案 2 :(得分:0)

您在对象的原型上添加的任何内容都将出现在该对象的所有实例中。这就是我们如何在javascript中扩展对象。

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

答案 3 :(得分:0)

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

  

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

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