javascript - map遍历 - js遍历数组




在JavaScript中循环遍历数组 (20)

在Java中,您可以使用for循环遍历数组中的对象,如下所示:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

你能用JavaScript做同样的事吗?


for(var s of myStringArray){

(直接回答你的问题:现在你可以!)

大多数其他答案是正确的,但他们没有提及(截至本文撰写时) ECMA Script 6 2015带来了一种新的迭代机制,即for..of循环。

这种新语法是在javascript中迭代数组的最优雅方式(只要你不需要迭代索引),但它还没有被浏览器广泛支持。

它目前适用于Firefox 13 +,Chrome 37+,它本身不能与其他浏览器一起使用(请参阅下面的浏览器兼容性)。 幸运的是,我们有JS编译器(如Babel ),它们允许我们今天使用下一代功能。

它也适用于Node(我在版本0.12.0上测试过它)。

迭代一个数组

// 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 ://wiki.ecmascript.org/doku.php? http://wiki.ecmascript.org/doku.php?id=harmony:iterators ethmony : http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}


最优雅,最快捷的方式

<script src="//code.jquery.com/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>

http://jsperf.com/native-loop-performance/8

编辑(因为我错了)

比较循环遍历100000个项目的数组的方法,并每次使用新值进行最小化操作。

制备:

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

测试:

for (var i in array) if (array.hasOwnProperty(i)) {
    // do something with array[i]
}

Opera,Safari,Firefox和Chrome现在都共享一组增强的Array方法,用于优化许多常见循环。

您可能不需要所有这些,但它们可能非常有用,或者如果每个浏览器都支持它们。

Mozilla Labs发布了他们和WebKit都使用的算法,因此您可以自己添加它们。

filter返回满足某些条件或测试的项目数组。

如果每个数组成员都通过测试,则返回true。

如果有任何通过测试,则返回true。

forEach在每个数组成员上运行一个函数,并且不返回任何内容。

map类似于forEach,但它返回每个元素的操作结果数组。

这些方法都为它们的第一个参数提供了一个函数,并且有一个可选的第二个参数,该参数是一个对象,当它们循环遍历函数时,它们要在数组成员上施加范围。

忽略它直到你需要它。

indexOflastIndexOf确切地找到与其参数匹配的第一个或最后一个元素的适当位置。

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

一些用例在JavaScript中以函数编程方式循环遍历数组:

1.只需循环一个数组

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

注意:严格来说,Array.prototype.forEach()不是一种功能方式,因为它作为输入参数所采用的函数不应该返回一个值,因此不能将其视为纯函数。

2.检查数组中的任何元素是否通过测试

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3.转换为新数组

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

注意:map()方法创建一个新数组,其结果是在调用数组中的每个元素上调用提供的函数。

4.总结一个特定的属性,并计算其平均值

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5.基于原始数组创建新数组,但不进行修改

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6.计算每个类别的数量

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7.根据特定条件检索数组的子集

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

注意:filter()方法创建一个新数组,其中包含所有传递由提供的函数实现的测试的元素。

8.对数组进行排序

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

9.在数组中查找元素

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

Array.prototype.find()方法返回数组中第一个满足提供的测试函数的元素的值。

参考


使用while循环...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

日志:'one','two','three'

而对于相反的顺序,一个更有效的循环

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

日志:'one','two','three'

参考: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


使用顺序for循环:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    alert(myStringArray[i]);
    //Do something
}

@zipcodeman建议使用for...in语句,但是应该避免迭代数组for-in ,该语句用于枚举对象属性。

它不应该用于类似数组的对象,因为:

  • 不保证迭代的顺序,可能无法按数字顺序访问数组索引。
  • 还枚举了继承的属性。

第二点是它可以给你很多问题,例如,如果你扩展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方法允许您只枚举自己的属性 ,就是它,只有对象物理上具有的属性,没有继承属性。

我建议你阅读以下文章:


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

看看this有关详细信息,或者你也可以检查for...in在JavaScript中循环一个数组并使用jQuery检查jQuery.each()


在JavaScript中,不建议使用for-in循环遍历数组,但最好使用for循环,例如:

for(var i=0, len=myArray.length; i < len; i++){}

它也被优化(“缓存”数组长度)。 如果您想了解更多信息,请阅读我关于该主题的帖子


如果你想使用jQuery,它的文档中有一个很好的例子:

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });

如果你想要一种简洁的方法来编写一个快速循环你可以反向迭代:

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

这有利于缓存长度(类似于for (var i=0, len=myArray.length; i<len; ++i)而不像for (var i=0; i<myArray.length; ++i) )同时输入更少的字符。

甚至有些时候你应该反向迭代,例如当迭代在一个实时NodeList上 ,你计划在迭代期间从DOM中删除项目。


它不是100%完全相同,但相似:

   var myStringArray = ['Hello', 'World']; // array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }


当然它效率低下而且很多人鄙视它,但它是最接近上述之一的:

var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
    // Do something
})

我完全建议使用underscore.js库。 它为您提供了各种可用于迭代数组/集合的函数。

例如:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

我还没有看到这种变化,我个人最喜欢这种变化:

给定一个数组:

var someArray = ["some", "example", "array"];

您可以在不访问length属性的情况下遍历它:

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/http://jsfiddle.net/prvzk/

这仅适用于稀疏的数组。这意味着数组中的每个索引实际上都有一个值。但是,我发现在实践中我几乎没有在Javascript中使用稀疏数组......在这种情况下,将对象用作map / hashtable通常要容易得多。如果你有一个稀疏数组,并希望循环遍历0 .. length-1,你需要for(var i = 0; i <someArray.length; ++ i)构造,但是你仍需要一个if循环以检查当前索引处的元素是否实际定义。

此外,正如CMS在下面的注释中提到的那样,您只能在不包含任何伪造值的数组上使用它。示例中的字符串数组有效,但如果您有空字符串,或者数字为0或NaN等,则循环将过早中断。再次在实践中,这对我来说几乎不是问题,但是要记住这一点,这使得在使用它之前需要考虑这个循环...这可能会使某些人取消它的资格:)

我喜欢这个循环是:

  • 这是写作的简短
  • 无需访问(更不用说缓存)length属性
  • 要访问的项目将在您选择的名称下在循环体内自动定义。
  • 与array.push和array.splice非常自然地结合使用像列表/堆栈这样的数组

这样做的原因是数组规范要求当你从索引> =数组的长度读取一个项目时,它将返回undefined。当您写入这样的位置时,它实际上会更新长度。

对我来说,这个结构最接近地模仿我喜欢的Java 5语法:

for (String item : someArray) {
}

...还有了解循环内当前索引的额外好处


是的,但前提是您的实现包括ECMAScript 2015中引入的for ...功能(“Harmony”版本)。

它的工作原理如下:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

或者更好,因为ECMAScript 2015还通过letconst提供了块范围的变量:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const 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 ...
  }
}

将长度值分配给局部变量(与在循环条件中包含完整的myStringArray.length表达式相反)可以在性能上产生显着差异,因为它每次都会跳过属性查找; 在我的机器上使用Rhino,加速比为43%。

您将经常在循环初始化子句中看到完成的长度缓存,如下所示:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

其他人提到的for ... in语法用于循环对象的属性; 因为JavaScript中的数组只是一个具有数字属性名称的对象(以及一个自动更新的length属性),所以理论上可以用它循环一个数组。 但问题是它并不局限于数值属性值(请记住,即使方法实际上只是其值为闭包的属性),也不会按数字顺序迭代它们。 因此, for ... in语法应该用于循环遍历Arrays。


是的,您可以在JavaScript中使用循环执行相同的操作,但不限于此,在JavaScrip中执行循环数组的许多方法,假设您在下面有这个数组,并且您想对它进行循环:

var arr = [1, 2, 3, 4, 5];

这些是解决方案:

1)for循环

For循环是在JavaScript中循环遍历数组的常用方法,但不被认为是大型数组的最快解决方案:

for (var i=0, l=arr.length; i<l; i++) { 
  console.log(arr[i]);
}

2)while循环

虽然循环被认为是循环遍历长数组的最快方法,但通常在JavaScript中使用较少:

let i=0;

while (arr.length>i) {
    console.log(arr[i]);
    i++;
}

3)做同时
做同样的事情,但有一些语法差异如下:

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

这些是进行javascript循环的主要方法,但还有更多方法可以做到这一点。

我们还使用for in循环来循环javascript中的对象。

另外,也要看看map()filter()reduce()等功能于JavaScript的数组。他们可能比使用while和更快更好地做事for

如果您想了解有关JavaScript中数组的异步函数的更多信息,这是一篇很好的文章。

如今,功能编程在开发领域引起了轰动。并且有充分的理由:功能技术可以帮助您编写更多的声明性代码,一目了然,重构和测试更容易理解。

函数式编程的基石之一是它对列表和列表操作的特殊使用。而那些东西正是它们的声音:事物的数组,以及你对它们所做的事情。但功能性思维方式对待它们的方式与您的预期不同。

本文将仔细研究我所谓的“三大”列表操作:map,filter和reduce。围绕这三个功能进行思考是朝着能够编写干净的功能代码迈出的重要一步,并为功能和反应式编程的强大技术打开了大门。

这也意味着你永远不必再次编写for循环。

阅读更多>> here


有一种方法可以在循环中具有非常小的隐式范围并且消除额外的变量。

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原型forEachmapreducefilter和许多其他方法的迭代器方法。


在JavaScript中有两种方法可以做到这一点。前两个示例是JavaScript示例。第三个使用JavaScript库,即jQuery使用该.each()函数。

var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
  alert(value);
})

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}


我认为最好的方法是使用Array.forEach函数。如果您不能使用我建议从MDN获取polyfill使我可用,它肯定是在JavaScript中迭代数组的最安全的方法。

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

正如其他人所说,这几乎总是你想要的:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

这样可以确保在处理数组范围内所需的任何内容都保留在该范围内,并且您只处理数组的值,而不是对象属性和其他成员,这就是.. in。

在大多数情况下,使用常规c样式for循环工作,重要的是要记住循环中的所有内容与程序的其余部分共享它的范围,{}不会创建新的范围。

因此:

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

将输出“11” - 这可能是也可能不是你想要的。

工作jsFiddle示例:https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/://jsfiddle.net/workingClassHacker/pxpv2dh5/7/https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/


简短回答:是的。你可以这样做:

var myArray = ["element1", "element2", "element3", "element4"];

for (i = 0; i < myArray.length; i++) {
  console.log(myArray[i]);
}

在浏览器控制台中,您可以看到打印的“element1”,“element2”等内容。





for-loop