赋予 Array.prototype 的 JS 函数被视为数组属性

发布于 2024-12-09 02:16:52 字数 570 浏览 0 评论 0原文

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 循环的代码,因为它是外部库。因此,问题的提出更多地是关于“为什么会这样”,而不是如何解决这个问题。

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]);
}

This will log (in chrome)

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

Or live example in http://jsfiddle.net/marqs/6VVka/1/

My question is, why is the function shown in the listing, even though it's given to the array prototype?

This has implications for extending browser functionalities that aren't used (for ex. IE extended Array.filter will behave differently if array in is used etc).

Edit:
to clarify, I have no access to the code that does the for-in loop, as it's an external library. Thus the formulation of the question, more about "why is this so" than how to fix this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不一样的天空 2024-12-16 02:16:52

JavaScript 对象是属性的集合。在这些属性内部,有一些描述属性的属性。您在这里看到的主要属性是 [[Enumerable]] 属性,它是一种扩展至 JavaScript 中大多数默认对象(例如数组和对象)的元属性。 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/

JavaScript Objects are a collection of properties. Inside these properties, there are properties that describe the properties. The main one you are looking at here is the [[Enumerable]] property, which is a meta-property extended to most of the default objects in JavaScript, such as Array and Object. ECMAScript 5 defines a method for adding non-[[Enumerable]] objects, but that may not be widely supported in browsers.

One way to prevent enumerating over object properties you don't want is to check if the object property has an internal property method called [[GetOwnProperty]]. This ensures the property was directly invoked on the object and NOT inherited somewhere along the prototype chain.

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"]

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

掩耳倾听 2024-12-16 02:16:52

for-in 循环将循环遍历对象的所有继承属性及其自身属性。 Ecmascript 5 中有一种方法可以隐藏枚举属性,请参阅 Ecmascript 5 对象和属性,但这在 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 变量。

The for-in loop will loop though all inherited properties of an object as well as its own properties. There is a way in Ecmascript 5 to hide your properties from enumeration, see Ecmascript 5 Objects and Properties, but this doesn't work in IE. The recommended way to iterate an array is to use the normal for loop:

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

This will have much better performance than the for-in loop as well because it avoids looking for properties on the object through the prototype chain. The len variable is used to cache the length of the array to avoid looking it up on each iteration of the loop. If you want to be slick, you can:

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

This iterates the array in reverse, and avoids the additional len variable.

几味少女 2024-12-16 02:16:52

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

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

Any thing you add on an object's prototype, will appear in all of the instances of that object. This is how we can extend objects in javascript.

Please refer to: http://phrogz.net/js/classes/ExtendingJavaScriptObjectsAndClasses.html

七婞 2024-12-16 02:16:52

显然道格拉斯·克罗克福德(Douglas Crockford)写过同样的问题。

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

http://yuiblog.com/blog/2006/09/26/为了阴谋/

Apparently Douglas Crockford has written about the same issue.

The flaw is that the for in statement, which can enumerate the keys
stored in an object, produces all of the keys in the object’s
prototype chain, not just the keys in the object itself. This causes
inherited methods to appear in the enumeration, which is bad. If would
have been nicer if JavaScript did not contain this flaw, but
fortunately we can program around it.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文