我被告知不要使用。。。在JavaScript中使用数组。为什么不呢?
当前回答
您应该只在属性列表上使用for(var x in y),而不是在对象上(如上所述)。
其他回答
TL&DR:在数组中使用for in循环并不是坏事,事实上恰恰相反。
我认为如果在数组中正确使用,for in循环是JS的瑰宝。你应该完全控制你的软件,并知道你在做什么。让我们看看上面提到的缺点,并逐一反驳它们。
它还遍历继承的财产:首先,对Array.prototype的任何扩展都应该使用Object.defineProperty()完成,并且它们的可枚举描述符应该设置为false。任何没有这样做的库都不应该被使用。添加到继承链中的财产稍后会被计数:当按Object.setPrototypeOf或按类扩展进行数组子分类时。您应该再次使用Object.defineProperty(),它默认将可写、可枚举和可配置的属性描述符设置为false。让我们在这里看到一个数组子类示例。。。
函数堆栈(…a){var stack=新数组(…a);Object.setPrototypeOf(堆栈,stack.prototype);返回堆栈;}Stack.prototype=对象.create(Array.prototype);//现在堆栈可以完全访问数组方法。Object.defineProperty(Stack.prototype,“constructor”,{value:Stack});//现在Stack是一个合适的构造函数Object.defineProperty(Stack.prototype,“peak”,{value:function(){//将Stack“only”方法添加到Stack.prototype。返回this[this.length-1];}});var s=新堆栈(1,2,3,4,1);console.log(s.peak());s[s.length]=7;console.log(“长度:”,s.length);s.push(42);console.log(JSON.stringify);console.log(“长度:”,s.length);for(var i in s)console.log(s[i]);
所以你看。。因为您关心代码,所以in循环现在是安全的。
for in循环很慢:见鬼,没有。如果你在不时需要的稀疏数组上循环,这是迄今为止最快的迭代方法。这是人们应该知道的最重要的表演技巧之一。让我们看一个例子。我们将在稀疏数组上循环。
变量a=[];a[0]=“零”;a[10000000]=“1000万”;console.time(“用于数组a上的循环:”);对于(var i=0;i<a.length;i++)a[i]&&console.log(a[i]);console.timeEnd(“用于数组a上的循环:”);console.time(“用于数组a上的循环:”);对于(a中的var i)a[i]&&console.log(a[i]);console.timeEnd(“用于数组a上的循环中:”);
for in语句本身并不是一个“坏习惯”,但是它可能被错误地使用,例如,用于迭代数组或类似数组的对象。
for-in语句的目的是枚举对象财产。该语句将出现在原型链中,也会枚举继承的财产,这有时是不需要的。
此外,规范并不能保证迭代的顺序,这意味着如果要“迭代”数组对象,那么使用此语句无法确保财产(数组索引)将按数字顺序访问。
例如,在JScript(IE<=8)中,即使在Array对象上,枚举的顺序也定义为创建了财产:
var array = [];
array[2] = 'c';
array[1] = 'b';
array[0] = 'a';
for (var p in array) {
//... p will be "2", "1" and "0" on IE
}
此外,谈到继承的财产,例如,如果您扩展Array.prototype对象(像MooTools这样的一些库),那么财产也会被枚举:
Array.prototype.last = function () { return this[this.length-1]; };
for (var p in []) { // an empty array
// last will be enumerated
}
正如我之前所说的,迭代数组或类似数组的对象,最好的方法是使用顺序循环,例如普通的旧for/while循环。
如果只想枚举对象自己的财产(未继承的属性),可以使用hasOwnProperty方法:
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// prop is not inherited
}
}
有些人甚至建议直接从Object.prototype调用该方法,以避免在有人向我们的对象添加名为hasOwnProperty的属性时出现问题:
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
// prop is not inherited
}
}
由于JavaScript元素保存为标准对象财产不建议使用for…遍历JavaScript数组。。。在里面循环,因为普通元素和所有可枚举的财产上市的
从…起https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections
正在使用。。。虽然我可以猜到为什么有人告诉你:
1.)已经有一个更高阶的函数或方法用于数组,但具有更多的功能和更精简的语法,称为“forEach”:array.protocol.forEach(函数(元素、索引、数组){});
2.)数组总是有长度的,但对于。。。in和forEach不会对任何“undefined”值执行函数,只对定义了值的索引执行函数。因此,如果只分配一个值,这些循环将只执行一次函数,但由于数组是枚举的,因此它的长度将始终达到具有定义值的最高索引,但在使用这些循环时,该长度可能会被忽略。
3.)循环的标准将执行函数的次数与您在参数中定义的次数相同,并且由于数组是编号的,因此定义您希望执行函数的数量更有意义。与其他循环不同,for循环可以为数组中的每个索引执行函数,无论是否定义了值。
本质上,您可以使用任何循环,但您应该记住它们是如何工作的。了解不同循环重复的条件及其各自的功能,并认识到它们或多或少适合不同的场景。
此外,使用forEach方法可能比使用for。。。一般来说,在循环中,因为它更容易编写并且具有更多的功能,所以您可能希望养成只使用此方法和标准的习惯,而不是使用您的调用。
请参见下面的内容,前两个循环只执行一次console.log语句,而标准for循环执行指定次数的函数,在本例中,array.length=6。
var arr = [];
arr[5] = 'F';
for (var index in arr) {
console.log(index);
console.log(arr[index]);
console.log(arr)
}
// 5
// 'F'
// => (6) [undefined x 5, 6]
arr.forEach(function(element, index, arr) {
console.log(index);
console.log(element);
console.log(arr);
});
// 5
// 'F'
// => Array (6) [undefined x 5, 6]
for (var index = 0; index < arr.length; index++) {
console.log(index);
console.log(arr[index]);
console.log(arr);
};
// 0
// undefined
// => Array (6) [undefined x 5, 6]
// 1
// undefined
// => Array (6) [undefined x 5, 6]
// 2
// undefined
// => Array (6) [undefined x 5, 6]
// 3
// undefined
// => Array (6) [undefined x 5, 6]
// 4
// undefined
// => Array (6) [undefined x 5, 6]
// 5
// 'F'
// => Array (6) [undefined x 5, 6]
除了其他答案中给出的原因外,如果需要计算计数器变量,您可能不想使用“for…In”结构,因为循环会迭代对象财产的名称,因此该变量是一个字符串。
例如
for (var i=0; i<a.length; i++) {
document.write(i + ', ' + typeof i + ', ' + i+1);
}
将写入
0, number, 1
1, number, 2
...
鉴于
for (var ii in a) {
document.write(i + ', ' + typeof i + ', ' + i+1);
}
将写入
0, string, 01
1, string, 11
...
当然,这可以通过包括
ii = parseInt(ii);
但第一种结构更直接。
推荐文章
- 在数组中获取所有选中的复选框
- 如何为Firebase构建云函数,以便从多个文件部署多个函数?
- 如何发送推送通知到web浏览器?
- AngularJS:工厂和服务?
- js:将一个组件包装成另一个组件
- 父ng-repeat从子ng-repeat的访问索引
- 如何读一个文本文件到一个列表或数组与Python
- JSHint和jQuery: '$'没有定义
- 模仿JavaScript中的集合?
- 如何在Python中将十六进制字符串转换为字节?
- 用JavaScript验证电话号码
- 如何在HTML5中改变视频的播放速度?
- 谷歌地图API v3:我可以setZoom后fitBounds?
- ES6/2015中的null安全属性访问(和条件赋值)
- 与push()相反;