我在我的网络应用程序的主JavaScript中有以下代码:
// uniq for arrays
if (!Array.prototype.getUnique) {
Array.prototype.getUnique = function () {
var u = {}, a = [];
for (var i = 0, l = this.length; i < l; ++i) {
if (u.hasOwnProperty(this[i])) {
continue;
}
a.push(this[i]);
u[this[i]] = 1;
}
return a;
}
}
它是javascript的简单uniq
克隆,monkeypatched到基本的Array类中。 (请不要在这里讨论monkeypatching,请点击其他地方......)
getUnique()
按预期工作,但现在每当我使用for...in
循环迭代一个数组时,另一个名为getUnique
的索引将传递给迭代器主体,并且当此为false {查找{1}},n
的代码是值。 (换句话说:getUnique
正在循环遍历数组,但在最后一次迭代时追加for...in
这里发生了什么?还有另一个monkeypatched函数在这个函数的正上方工作正常(getUnique
)并且没有出现在迭代器中。以下是一些触发此问题的示例代码:
indexOf()
此代码段的调试输出如下所示:
for (var r in result) {
//tags = tags + result[r]["tags"].split(" ").join(", ")
if (result[r]["tags"]) {
var newtags = result[r]["tags"].split(" ");
debug.log(newtags);
for (var n in newtags) {
debug.log("n is " + n);
tags.push(newtags[n]);
}
}
}
这里发生了什么?重构monkeypatch并将其放在实用程序类中很容易,但对我来说这是一个非常奇怪的边缘情况。我脑子里想到了这里发生的事情,但这些只是猜测。谁能解释一下?
答案 0 :(得分:1)
这是hasOwnProperty
旨在解决的问题:它告诉您迭代的名称是在对象本身上还是从原型继承。
试试这个:
for (var n in newtags) {
if (newtags.hasOwnProperty(n)) {
debug.log("n is " + n);
tags.push(newtags[n]);
}
}
答案 1 :(得分:1)
不要使用for-in
来迭代数字属性。
使用for
循环:
for (var i = 0; i < newtags.length; i++) {
for-in
语句几乎从来都不是这项工作的合适工具,因为......
它包括所有属性,包括非数字,超出范围和原型属性。
它不保证枚举的顺序。
虽然你可以进行hasOwnProperty
检查,但没有真正的好处,并且有一些缺点......
它会减慢你的迭代次数
它对枚举问题的顺序没有帮助
有时你想要一个原型索引(很少见,但它会发生)。使用hasOwnProperty
会使这变得不可能。
答案 2 :(得分:1)
您不应使用for…in
循环遍历数组,该循环用于枚举对象的属性。因此,例如,您无法保证索引的顺序,也没有 - 如您所见 - 您只迭代数字索引。如果其他人以这种方式向Array的原型添加属性,您也将迭代该属性。请参阅https://developer.mozilla.org/en/JavaScript/Reference/Statements/for...in以获得完整的图片。
但是,在您的情况下,您可以执行以下操作:
for (var n in newtags) {
if (newtags.hasOwnProperty(n)) {
debug.log("n is " + n);
tags.push(newtags[n]);
}
}
这也阻止了迭代由其他脚本添加到原型的属性。此外,您可以将您的功能定义为不可枚举(在支持ES5的浏览器中):
Object.defineProperty(Array.prototype, "getUnique", {
value: function () { /*.. your function ..*/}
})
请参阅:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
答案 3 :(得分:1)
常见的误解是,在...中运行for ...是为了迭代数组。这是错的。它的用法是迭代对象的任何可枚举属性。在javascript中,一切都是对象(包括数组)。但是你可能会注意到,当你在数组中执行...时,你不会得到像length,slice等的值。这是因为那些不是对象的可枚举属性。
这个SO问题提供了一些关于for ... in Why is using "for...in" with array iteration a bad idea?
的使用情况的非常好的信息如果你想坚持使用for ... in,你可以像上面建议的那样做,并检查你的forOwnProperty ...
for ( var v in myArray ) {
if ( myArray.hasOwnProperty(v) ) {
// Do Something
}
}
然而,我建议使用普通的无聊循环...
for ( var i = 0; i <= myArray.length - 1; i++ ) {
// Do Something
}
没有疯狂的细节,这可以在没有达到你添加的方法的情况下工作,因为数组的“索引”根本不是真正的索引,而是具有与其相应索引匹配的名称的属性:即1,0,4等等。
他们感觉像是索引,因为在javascript中,如果该属性是一个数字(即:myArray.0将无效),则无法使用点表示法访问该属性。所以你做myArray [0],感觉就像一个数组。