在JavaScript中循环访问数组
在Java中,您可以使用for
循环遍历数组中的对象,如下所示:
String[] myStringArray = {"Hello", "World"}; for (String s : myStringArray) { // Do something }
你可以在JavaScript中做同样的事情吗?
使用顺序for
循环:
var myStringArray = ["Hello","World"]; var arrayLength = myStringArray.length; for (var i = 0; i < arrayLength; i++) { alert(myStringArray[i]); //Do something }
@zipcodemanbuild议使用for...in
语句,但是为了迭代数组for-in
应该避免,该语句旨在枚举对象属性。
它不应该用于类似数组的对象,因为:
- 迭代顺序不能保证,数组索引可能不会按数字顺序访问。
- inheritance的属性也被枚举。
第二点是,它可以给你很多的问题,例如,如果你扩展Array.prototype
对象在那里包含一个方法,该属性也将被枚举。
例如:
Array.prototype.foo = "foo!"; var array = ['a', 'b', 'c']; for (var i in array) { alert(array[i]); }
上面的代码会提醒“a”,“b”,“c”和“foo!”。
如果你使用一些依赖于本地原型扩展的库(例如MooTools),那么这个问题尤其会成为一个问题。
我之前说过的for-in
语句是枚举对象的属性,例如:
var obj = { "a": 1, "b": 2, "c": 3 }; for (var prop in obj) { if (obj.hasOwnProperty(prop)) { // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety... alert("prop: " + prop + " value: " + obj[prop]) } }
在上面的例子中, hasOwnProperty
方法允许你只枚举自己的属性 ,就是它,只有对象的物理属性,没有inheritance的属性。
我build议你阅读下面的文章:
- 枚举VS迭代
是的,但前提是您的实施包括ECMAScript 2015 (“和谐”版本)中引入的for
…function。
它是这样工作的:
// REQUIRES ECMASCRIPT 2015+ var s, myStringArray = ["Hello", "World"]; for (s of myStringArray) { // ... do something with s ... }
或者更好,因为ECMAScript 2015还通过let
和const
提供了块范围的variables:
// REQUIRES ECMASCRIPT 2015+ const myStringArray = ["Hello", "World"]; for (let s of myStringArray) { // ... do something with s ... } // s is no longer defined here
然而,许多JavaScript开发人员仍然在一个尚不存在的环境中工作,特别是编写代码在Web浏览器中运行时,网站开发人员往往无法确定客户端将使用哪种浏览器/版本。
如果您可以假设JavaScript解释器符合ECMAScript规范的先前版本(例如排除9之前的Internet Explorer版本),则可以使用forEach
迭代器方法而不是循环。 在这种情况下,你传递一个函数来调用数组中的每个项目:
var myStringArray = [ "Hello", "World" ]; myStringArray.forEach( function(s) { // ... do something with s ... } );
但是,即使这个假设太多了,而且你想要所有版本的JavaScript 都有效的东西,那么你必须使用一个明确的计数循环。 最安全的版本,正确处理稀疏数组,是这样的:
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length; for (i=0; i<len; ++i) { if (i in myStringArray) { s = myStringArray[i]; // ... do something with s ... } }
将长度值赋给局部variables(而不是在循环条件中包含完整的myStringArray.length
expression式)可以在性能上产生显着的差异,因为每次都跳过属性查找; 在我的机器上使用犀牛,加速是43%。
您经常会在循环初始化子句中看到长度caching,如下所示:
var i, len, myStringArray = [ "Hello", "World" ]; for (len = myStringArray.length, i=0; i<len; ++i) {
其他人提到的for
…语法是为了遍历对象的属性; 因为JavaScript中的数组只是一个具有数字属性名称(和一个自动更新的length
属性)的对象,理论上你可以用它循环一个数组。 但问题是它不会将自身限制为数字属性值(请记住,即使方法实际上只是其值为闭包的属性),也不会按数字顺序迭代。 因此, for
… in
语法不应该用于循环数组。
您可以使用map
,这是一种function丰富的编程技术,也可用于其他语言,如Python和Haskell 。
[1,2,3,4].map( function(item) { alert(item); })
一般的语法是:
array.map(func)
一般来说, func
会带一个参数,这个参数是数组的一个项目。 但在Javascript的情况下,它可以采取第二个参数,这是项目的索引,第三个参数是数组本身。
array.map
的返回值是另一个数组,所以你可以像这样使用它:
var x = [1,2,3,4].map( function(item) { return item * 10; } );
现在x是[10,20,30,40]
。
您不必内联编写函数。 它可能是一个单独的function。
var item_processor = function(item) { // do something complicated to an item } new_list = my_list.map(item_processor);
这将是相当于:
for(item in my_list) { item_processor(item); }
除非你没有得到new_list
。
在JavaScript中,不build议使用for-in循环来循环访问数组,但最好使用for循环,例如:
for(var i=0, len=myArray.length; i < len; i++){}
它也被优化(“caching”数组长度)。 如果您想了解更多信息,请阅读我的post 。
for(var s of myStringArray){
(直接回答你的问题:现在你可以!)
大多数其他答案是正确的,但是他们没有提到(截至本文), ECMA Script 6 2015正在为迭代, for..of
循环带来新的机制。
这个新的语法是在javascript中迭代一个数组的最优雅的方法(只要你不需要迭代索引),但是它还没有得到浏览器的广泛支持。
它目前与Firefox 13+,Chrome 37+兼容,并且不会与其他浏览器本身一起工作(请参阅下面的浏览器兼容性)。 幸运的是,我们有JS编译器(比如Babel ),可以让我们今天使用下一代function。
它也适用于Node(我在0.12.0版本上testing过)。
迭代一个数组
// You could also use "let" instead of "var" for block scope. for (var letter of ["a", "b", "c"]) { console.log(letter); }
迭代一组对象
var band = [ {firstName : 'John', lastName: 'Lennon'}, {firstName : 'Paul', lastName: 'McCartney'} ]; for(var member of band){ console.log(member.firstName + ' ' + member.lastName); }
迭代发生器:
(例子摘自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for…of )
function* fibonacci() { // a generator function let [prev, curr] = [1, 1]; while (true) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (let n of fibonacci()) { console.log(n); // truncate the sequence at 1000 if (n >= 1000) { break; } }
兼容性表格: http : //kangax.github.io/es5-compat-table/es6/#For..of循环
规格: http ://wiki.ecmascript.org/doku.php? id= harmony: iterators
}
Opera,Safari,Firefox和Chrome现在都共享一套增强的数组方法来优化许多常见的循环。
你可能不需要所有这些,但是它们可以是非常有用的,或者如果每个浏览器都支持它们的话。
Mozilla实验室发布了他们和WebKit都使用的algorithm,以便您可以自己添加它们。
filter返回满足某些条件或testing的项目数组。
如果每个数组成员通过testing,则每个返回true。
如果有任何通过testing, 一些返回true。
forEach在每个数组成员上运行一个函数并且不返回任何东西。
映射就像forEach,但它返回每个元素的操作结果数组。
这些方法全部为它们的第一个参数采用一个函数,并且有一个可选的第二个参数,这个参数是一个对象,当它们在函数中循环时,它的作用域就是在数组成员上施加的作用域。
忽略它,直到你需要它。
indexOf和lastIndexOf精确地查找与其参数匹配的第一个或最后一个元素的适当位置。
(function(){ var p, ap= Array.prototype, p2={ filter: function(fun, scope){ var L= this.length, A= [], i= 0, val; if(typeof fun== 'function'){ while(i< L){ if(i in this){ val= this[i]; if(fun.call(scope, val, i, this)){ A[A.length]= val; } } ++i; } } return A; }, every: function(fun, scope){ var L= this.length, i= 0; if(typeof fun== 'function'){ while(i<L){ if(i in this && !fun.call(scope, this[i], i, this)) return false; ++i; } return true; } return null; }, forEach: function(fun, scope){ var L= this.length, i= 0; if(typeof fun== 'function'){ while(i< L){ if(i in this){ fun.call(scope, this[i], i, this); } ++i; } } return this; }, indexOf: function(what, i){ i= i || 0; var L= this.length; while(i< L){ if(this[i]=== what) return i; ++i; } return -1; }, lastIndexOf: function(what, i){ var L= this.length; i= i || L-1; if(isNaN(i) || i>= L) i= L-1; else if(i< 0) i += L; while(i> -1){ if(this[i]=== what) return i; --i; } return -1; }, map: function(fun, scope){ var L= this.length, A= Array(this.length), i= 0, val; if(typeof fun== 'function'){ while(i< L){ if(i in this){ A[i]= fun.call(scope, this[i], i, this); } ++i; } return A; } }, some: function(fun, scope){ var i= 0, L= this.length; if(typeof fun== 'function'){ while(i<L){ if(i in this && fun.call(scope, this[i], i, this)) return true; ++i; } return false; } } } for(p in p2){ if(!ap[p]) ap[p]= p2[p]; } return true; })();
使用while循环…
var i=0, item, items = ['one','two','three']; while(item = items[i++]){ console.log(item); }
日志:“一”,“二”,“三”
而对于相反的顺序,更有效的循环
var items = ['one','two','three'], i = items.length; while(i--){ console.log(items[i]); }
日志:“三”,“二”,“一”
或古典for
循环
var items = ['one','two','three'] for(var i=0, l = items.length; i < l; i++){ console.log(items[i]); }
日志:“一”,“二”,“三”
参考: http : //www.sitepoint.com/google-closure-how-not-to-write-javascript/
如果你想要一个简洁的方式来写一个快速循环,你可以反向迭代:
for (var i=myArray.length;i--;){ var item=myArray[i]; }
这有利于caching长度(类似于for (var i=0, len=myArray.length; i<len; ++i)
而不像for (var i=0; i<myArray.length; ++i)
),而键入的字符更less。
甚至有时候你应该反向迭代,例如迭代一个活动的NodeList ,在迭代过程中你计划从DOM中删除项目。
介绍
自从我上大学以来,我已经用Java,JavaScript,Pascal, ABAP ,PHP,Progress 4GL,C / C ++以及其他几种我现在无法想象的语言编程。
虽然他们都有自己的语言特质,但是每种语言都有许多相同的基本概念。 这样的概念包括程序/函数, IF
语句, FOR
-loop和WHILE
-loops。
传统for
回旋
传统的for
循环有三个组件:
- 初始化:在第一次执行look块之前执行
- 条件:每次在循环块执行前检查一个条件,如果为false则退出循环
- 事后考虑:循环块执行后每次执行
这三个组成部分是相互分开的;
符号。 这三个组件的内容是可选的,这意味着以下是可能的最小循环:
for (;;) { // Do stuff }
当然,你需要包含一个if(condition === true) { break; }
if(condition === true) { break; }
或者一个if(condition === true) { return; }
为了让它停止运行,在里面的某处。
通常情况下,初始化用于声明一个索引,条件用于比较该索引与最小或最大值,后续用于增加索引:
for (var i = 0, length = 10; i < length; i++) { console.log(i); }
使用传统的for
循环来遍历数组
在数组中循环的传统方式是这样的:
for (var i = 0, length = myArray.length; i < length; i++) { console.log(myArray[i]); }
或者,如果你喜欢向后循环,你可以这样做:
for (var i = myArray.length - 1; i > -1; i--) { console.log(myArray[i]); }
然而,可能有许多变化,例如这个:
for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) { console.log(value); }
…或者这个…
var i = 0, length = myArray.length; for (; i < length;) { console.log(myArray[i]); i++; }
…或者这个:
var key = 0, value; for (; value = myArray[key++];){ console.log(value); }
无论哪个工作最好,主要是个人的品味和你正在实施的具体用例。
请注意,所有浏览器都支持这些变体,包括非常古老的变体!
一个while
循环
for
循环的一个替代方法是while
循环。 要循环访问数组,可以这样做:
var key = 0; while(value = myArray[key++]){ console.log(value); }
像传统的for
循环一样,即使最老的浏览器也支持while
循环。
另外,请注意,每个while循环都可以重写为for
循环。 例如,上面的while
循环的行为与for
循环的完全相同:
for(var key = 0; value = myArray[key++];){ console.log(value); }
For...in
而for...of
在JavaScript中,你也可以这样做:
for (i in myArray) { console.log(myArray[i]); }
但是,这应该谨慎使用,因为它在所有情况下都不像传统for
循环一样,并且有潜在的副作用需要考虑。 请参阅为什么在数组迭代中使用“for … in”是一个坏主意? 更多细节。
作为…的替代scheme,现在还有for...of
。 以下示例显示了for...of
循环与for...in
循环之间的区别:
var myArray = [3, 5, 7]; myArray.foo = "hello"; for (var i in myArray) { console.log(i); // logs 0, 1, 2, "foo" } for (var i of myArray) { console.log(i); // logs 3, 5, 7 }
此外,您需要考虑的是没有Internet Explorer支持的版本( Edge 12+ ),而且至less需要Internet Explorer 10。
Array.prototype.forEach()
for
-loops的替代方法是Array.prototype.forEach()
,它使用以下语法:
myArray.forEach(function(value, key, myArray) { console.log(value); });
所有现代浏览器以及Internet Explorer 9和更高版本均支持Array.prototype.forEach()
。
图书馆
最后,许多实用程序库也有自己的foreach
变体。 AFAIK,三个最stream行的是这些:
jQuery.each()
,在jQuery中 :
$.each(myArray, function(key, value) { console.log(value); });
_.each()
,在_.each()
中:
_.each(myArray, function(value, key, myArray) { console.log(value); });
_.forEach()
,在Lodash.js中 :
_.forEach(myArray, function(value, key) { console.log(value); });
有一种方法可以在你的循环中有很less的隐式作用域,并且消除额外的variables。
var i = 0, item; // note this is weak to sparse arrays or falsey values for ( ; item = myStringArray[i++] ; ){ item; // This is the string at the index. }
或者如果你真的想得到这个id,并且有一个非常经典的for
循环:
var i = 0, len = myStringArray.length; // cache the length for ( ; i < len ; i++ ){ myStringArray[i]; // Don't use this if you plan on changing the length of the array }
现代浏览器都支持Array原型的迭代器方法forEach
, map
, reduce
, filter
和其他一些方法。
在JavaScript中循环数组有很多种方法。
通用循环:
var i; for (i = 0; i < substr.length; ++i) { // Do something with `substr[i]` }
ES5的forEach:
substr.forEach(function(item) { // Do something with `item` });
jQuery.each:
jQuery.each(substr, function(index, item) { // Do something with `item` (or `this` is also `item` if you like) });
看看这个详细的信息,或者你也可以检查MDN循环通过JavaScript中的数组和使用jQuery检查每个jQuery 。
我会彻底推荐使用underscore.js库。 它为您提供了可用于遍历数组/集合的各种函数。
例如:
_.each([1, 2, 3], function(num){ alert(num); }); => alerts each number in turn...
数组循环:
for(var i = 0; i < things.length; i++){ var thing = things[i]; console.log(thing); }
对象循环:
for(var prop in obj){ var propValue = obj[prop]; console.log(propValue); }
如果您使用jQuery库,请考虑使用http://api.jquery.com/jQuery.each/
从文档:
jQuery.each( collection, callback(indexInArray, valueOfElement) )
返回: 对象
说明: generics迭代器函数,可用于无缝遍历对象和数组。 具有长度属性(如函数的参数对象)的数组和类似数组的对象通过数字索引(从0到length-1)进行迭代。 其他对象通过它们的命名属性进行迭代。
$.each()
函数不同于$(selector).each()
,它用于遍历一个jQuery对象。$.each()
函数可以用来遍历任何集合,不pipe它是一个映射(JavaScript对象)还是一个数组。 在数组的情况下,每次callback都会传递一个数组索引和相应的数组值。 (该值也可以通过this
关键字来访问,但是Javascript总是将this
值作为一个Object
来包装,即使它是一个简单的string或数字值。)该方法返回它的第一个参数,即被迭代的对象。
我还没有看到这个变化,我个人喜欢最好的:
给定一个数组:
var someArray = ["some", "example", "array"];
你可以遍历它而不用访问长度属性:
for (var i=0, item; item=someArray[i]; i++) { // item is "some", then "example", then "array" // i is the index of item in the array alert("someArray[" + i + "]: " + item); }
看到这个JsFiddle展示: http : //jsfiddle.net/prvzk/
这只适用于不稀疏的数组。 意味着数组中的每个索引实际上都有一个值。 然而,我发现在实践中,我几乎没有在JavaScript中使用稀疏数组…在这种情况下,将对象用作映射/哈希表通常要容易得多。 如果你有一个稀疏的数组,并且要遍历0 .. length-1,你需要for(var i = 0; i <someArray.length; ++ i)构造,但是你仍然需要一个if循环来检查当前索引处的元素是否被实际定义。
另外,正如CMS在下面的评论中提到的,你只能在不包含任何falsish值的数组上使用它。 示例中的string数组有效,但是如果您有空string或数字是0或NaN等,则循环会过早地中断。 再次在实践中,这对我来说几乎不是一个问题,但要记住,这使得它成为一个循环,然后才能使用它…这可能会使某些人丧失资格:)
我喜欢这个循环是:
- 写的很简单
- 不需要访问(更不用说caching)长度属性
- 要访问的项目在您select的名称下自动定义在循环体内。
- 与array.push和array.splice自然结合使用像列表/堆栈数组
这个工作的原因是数组规范要求,当你从索引> =数组的长度读取一个项目,它将返回undefined。 当你写这样的位置时,它实际上会更新长度。
对我来说,这个构造最接近我模拟的Java 5语法:
for (String item : someArray) { }
另外还知道循环内的当前索引
There are a couple of ways to do it in JavaScript. The first two examples are JavaScript samples. The third one makes use of a JavaScript library, that is, jQuery making use of the .each()
function.
var myStringArray = ["hello", "World"]; for(var i in myStringArray) { alert(myStringArray[i]); }
The most elegant and fast way
var arr = [1, 2, 3, 1023, 1024]; for (var value; value = arr.pop();) { value + 1 }
http://jsperf.com/native-loop-performance/8
Edited (because I was wrong)
Comparing methods for looping through an array of 100000 items and do a minimal operation with the new value each time.
制备:
<script src="jquery-2.1.0.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script> <script> Benchmark.prototype.setup = function() { // Fake function with minimal action on the value var tmp = 0; var process = function(value) { tmp = value; // Hold a reference to the variable (prevent engine optimisation?) }; // Declare the test Array var arr = []; for (var i = 0; i < 100000; i++) arr[i] = i; }; </script>
Tests:
<a href="http://jsperf.com/native-loop-performance/16" title="http://jsperf.com/native-loop-performance/16" ><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>
There's a method to iterate over only own object properties, not including prototype's ones:
for (var i in array) if (array.hasOwnProperty(i)) { // do something with array[i] }
but it still will iterate over custom-defined properties.
In javascript any custom property could be assigned to any object including array.
If one wants to iterate over sparsed array, for (var i = 0; i < array.length; i++) if (i in array)
or array.forEach
with es5shim
should be used.
In JavaScript, there are so many solutions to loop an array.
The code below are popular ones
/** Declare inputs */ const items = ['Hello', 'World'] /** Solution 1. Simple for */ console.log('solution 1. simple for') for (let i = 0; i < items.length; i++) { console.log(items[i]) } console.log() console.log() /** Solution 2. Simple while */ console.log('solution 2. simple while') let i = 0 while (i < items.length) { console.log(items[i++]) } console.log() console.log() /** Solution 3. forEach*/ console.log('solution 3. forEach') items.forEach(item => { console.log(item) }) console.log() console.log() /** Solution 4. for-of*/ console.log('solution 4. for-of') for (const item of items) { console.log(item) } console.log() console.log()
The optimized approach is to cache the length of array and using single var pattern initializing all variables with single var keyword.
var i, max, myStringArray = ["Hello","World"]; for (i = 0, max = myStringArray.length; i < max; i++) { alert(myStringArray[i]); //Do something }
If order of iteration does not matter than you should try reversed loop, it is fastest as it reduce overhead condition testing and decrement is in one statement:
var i,myStringArray = ["item1","item2"]; for (i = myStringArray.length; i--) { alert(myStringArray[i]); }
or better and cleaner to use while loop:
var myStringArray = ["item1","item2"],i = myStringArray.length; while(i--) { // do something with fruits[i] }
The best way in my opinion is to use the Array.forEach function. If you cannot use that I would suggest to get the polyfill from MDN to make i available, it is certainly the safest way to iterate over an array in JavaScript.
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
So as others has suggested, this is almost always what you want:
var numbers = [1,11,22,33,44,55,66,77,88,99,111]; var sum = 0; numbers.forEach(function(n){ sum += n; });
This ensures that anything you need in the scope of processing the array stays within that scope, and that you are only processing the values of the array, not the object properties and other members, which is what for .. in does.
using a regular c style for loop works in most cases, it is just important to remember that everything within the loop shares it's scope with the rest of your program, the { } does not create a new scope.
因此:
var sum = 0; var numbers = [1,11,22,33,44,55,66,77,88,99,111]; for(var i = 0; i<numbers.length; ++i){ sum += numbers[i]; } alert(i);
will output "11" – which may or may not be what you want.
Working jsFiddle example: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/
Yes, you can do the same in JavaScript using loop, but not limited to that, many ways to do loop over arrays in JavaScrip, imagine you have this array below and you'd like to do a loop over it:
var arr = [1, 2, 3, 4, 5];
These are the solutions:
1) For loop
For loop is a common way looping through arrays in JavaScript, but no considered as the fastest solutions for large arrays:
for (var i=0, l=arr.length; i<l; i++) { console.log(arr[i]); }
2) While loop
While loop considered as the fastest way to loop through long arrays, but usually less used in the JavaScript:
var i=0; while (arr.length>i) { console.log(arr[i]); i++; }
3) Do while
Do while doing the same thing as while with some syntax difference as below:
var i=0; do { console.log(arr[i]); i++; } while (arr.length>i);
These are the main ways to do javascript loops, but there are few more ways to do that.
Also we use for in
loop for looping over objects in javascript.
Also look at map()
, filter()
, reduce()
etc functions on Array in JavaScript. They may do things much faster and better than using while
and for
.
This is good article if you like to learn more about the async functions over arrays in JavaScript.
Functional programming has been making quite a splash in the development world these days. And for good reason: Functional techniques can help you write more declarative code that is easier to understand at a glance, refactor, and test.
One of the cornerstones of functional programming is its special use of lists and list operations. And those things are exactly what the sound like they are: arrays of things, and the stuff you do to them. But the functional mindset treats them a bit differently than you might expect.
This article will take a close look at what I like to call the "big three" list operations: map, filter, and reduce. Wrapping your head around these three functions is an important step towards being able to write clean functional code, and opens the doors to the vastly powerful techniques of functional and reactive programming.
It also means you'll never have to write a for loop again.
Read more>> here :
For example, I used in a Firefox console:
[].forEach.call(document.getElementsByTagName('pre'), function(e){ console.log(e); })
简短的回答:是的。 You can do with this:
var myArray = ["element1", "element2", "element3", "element4"]; for (i = 0; i < myArray.length; i++) { console.log(myArray[i]); }
In a browser console, you can see something like "element1", "element2", etc., printed.
var x = [4, 5, 6]; for (i = 0, j = x[i]; i < x.length; j = x[++i]) { console.log(i,j); }
A lot cleaner…
Well, how about this:
for (var key in myStringArray) { console.log(myStringArray[key]); }
var myStringArray = ["hello", "World"]; myStringArray.forEach(function(val, index){ console.log(val, index); })
Sure it's inefficient and many despise it, but it's one of the closest to the mentioned:
var myStringArray = ["Hello","World"]; myStringArray.forEach(function(f){ // Do something })
var obj = ["one","two","three"]; for(x in obj){ console.log(obj[x]); }
It is better to use a sequential for
loop:
for (var i = 0; i < myStringArray.length; i++) { // Do something }