javascript - foreach跳出循环 - js遍历数组




For-each在JavaScript中的数组? (19)

向后循环

我认为反向循环值得一提:

for (var i = array.length; i--; ) {
     // process array[i]
}

好处:

  • 您不需要声明临时len变量,也不需要在每次迭代时与array.length进行比较,其中任何一个都可能是一个小时优化。
  • 以相反的顺序从DOM中删除兄弟姐妹通常更有效 。 (浏览器需要减少内部数组中元素的移动。)
  • 如果在循环时,在索引i处或之后修改数组 (例如,在array[i]删除或插入项目),则前向循环将跳过向左移动到位置i的项目 ,或者重新处理i那个向右移动的物品。 在传统的for循环中,您可以更新i以指向需要处理的下一个项目 - 1,但简单地反转迭代方向通常是一种更简单更优雅的解决方案
  • 类似地,当修改或移除嵌套的 DOM元素时,反向处理可以避免错误 。 例如,在处理子节点之前,请考虑修改父节点的innerHTML。 到达子节点时,它将与DOM分离,在写入父内部HTML时,已被新创建的子节点替换。
  • 键入和读取的时间比其他一些可用选项 。 虽然它失去了forEach()和ES6的for ... of

缺点:

  • 它以相反的顺序处理项目。 如果您从结果中构建新数组,或在屏幕上打印内容, 则输出将相对于原始顺序反转
  • 为了保留他们的顺序,重复地将兄弟姐妹插入DOM作为第一个孩子的效率较低 。 (浏览器将不得不改变方向。)要按顺序有效地创建DOM节点,只需循环前进并正常追加(并使用“文档片段”)。
  • 反向循环让初级开发人员感到困惑 。 (你可以认为这是一个优势,取决于你的前景。)

我应该经常使用它吗?

一些开发人员默认使用reverse for循环,除非有充分的理由向前循环。

虽然性能提升通常微不足道,但它有点尖叫:

“只需对列表中的每个项目执行此操作,我不关心订单!”

然而,在实践中,这实际上并不是意图的可靠指示,因为它与您关心订单的情况无法区分,并且确实需要反向循环。 因此实际上需要另一个构造来准确表达“不关心”的意图,这在大多数语言中目前都不可用,包括ECMAScript,但可以调用,例如, forEachUnordered()

如果顺序无关紧要, 效率是一个问题(在游戏或动画引擎的最内层循环中),那么使用反向循环作为你的首选模式是可以接受的。 请记住,在现有代码看到反向循环并不一定意味着订单无关紧要!

最好使用forEach()

一般来说,对于更高级别的代码,其中清晰度和安全性是更大的问题,我建议使用Array::forEach作为默认模式:

  • 很清楚阅读。
  • 它表明不会在块中移位(这总是可能会隐藏在long forwhile循环中。)
  • 它为您提供了一个免费的闭包范围。
  • 它减少了局部变量的泄漏以及外部变量的意外碰撞(和突变)。

然后,当你在代码中看到反向for循环时,这是一个暗示它被推翻的原因很充分(可能是上述原因之一)。 并且看到传统的前向循环可能表明可能发生转移。

(如果对意图的讨论对你没有意义,那么你和你的代码可能会受益于观看Crockford关于编程风格和你的大脑的讲座。)

它是如何工作的?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

您会注意到i--是中间子句(我们通常会看到比较),最后一个子句是空的(我们通常会看到i++ )。 这意味着我 - 也被用作继续的条件 。 至关重要的是,它会每次迭代之前执行并检查。

  • 它如何从array.length开始而不爆炸?

    因为i-- 每次迭代之前运行,所以在第一次迭代时我们实际上将访问array.length - 1处的项目,这避免了Array-out-of-bounds undefined项目的任何问题。

  • 为什么它不会在索引0之前停止迭代?

    当条件i--计算为假值(当它产生0时),循环将停止迭代。

    诀窍是,与--i不同,尾随的i--运算符递减i但在递减之前产生值。 你的控制台可以证明:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    所以在最后一次迭代中, 之前是1并且i--表达式将其更改为0但实际上产生1 (真实),因此条件通过。 在下一次迭代中, i--i更改为-1但产生0 (falsey),导致执行立即退出循环的底部。

    在循环的传统转发中, i++++i是可以互换的(正如Douglas Crockford指出的那样)。 但是在反向for循环中,因为我们的减量也是我们的条件表达式,所以如果我们想在索引0处理项目,我们必须坚持使用i--

琐事

有些人喜欢在反面画一个小箭头,然后以眨眼结束:

for (var i = array.length; i --> 0 ;) {

积分转到WYL,向我展示反向循环的好处和恐怖。

如何使用JavaScript循环遍历数组中的所有条目?

我以为它是这样的:

forEach(instance in theArray)

其中theArray是我的数组,但这似乎是不正确的。


摘要:

在遍历数组时,我们通常可能希望实现以下目标之一:

  1. 我们想迭代数组并创建新数组:

    Array.prototype.map

  2. 我们想迭代数组而不创建新数组:

    Array.prototype.forEach

    for..of

在JS中,有许多方法可以实现这两个目标。然而,有些人比其他人更有条理。下面你可以找到一些常用的方法(最方便的imo)来完成javascript中的数组迭代。

创建新数组: Map

map()是一个位于其上的函数Array.prototype,可以转换数组的每个元素,然后返回一个数组。map()将回调函数作为参数,并按以下方式工作:

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

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

我们map()作为参数传递的回调是针对每个元素执行的。然后返回一个与原始数组长度相同的数组。在这个新的数组元素由作为参数传入的回调函数转换map()

在不同的差异map和其他循环机制,就像forEach和一个for..of循环是map回报作为新的数组和离开旧阵列完好(除了这样想,如果你明确地操纵它splice)。

另请注意,map函数的回调提供了当前迭代的索引号作为第二个参数。此外,第三个参数提供了map被调用的数组。有时这些属性非常有用。

循环使用 forEach

forEach是一个函数,它位于Array.prototype一个回调函数作为参数。然后它为数组中的每个元素执行此回调函数。与map()函数相反,forEach函数不返回任何内容(undefined)。例如:

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

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

就像map函数一样,forEach回调提供了当前迭代的索引号作为第二个参数。第三个参数也提供了forEach被调用的数组。

循环使用元素 for..of

所述for..of的循环遍历的阵列(或任何其他迭代的对象)的每一个元素。它的工作方式如下:

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

for(let element of arr) {
  console.log(element * 2);
}

在上面的例子中element代表一个数组元素,arr是我们想要循环的数组。并非名称element是任意的,我们可以选择任何其他名称,如'el'或更适用的声明。

不要将for..in循环与for..of循环混淆。for..in将循环遍历数组的所有可枚举属性,而for..of循环将仅循环遍历数组元素。例如:

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

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}


从ES6开始:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

of避免了相关的怪异in,并使其喜欢的工作for任何其他语言的循环,并let结合i作为函数内相对于内环路。

{}当只有一个命令时(例如在上面的例子中),可以省略大括号()。


使用循环与ES6 destructuring扩展运算符

虽然一些javascript老手可能认为它很混乱,但是小辈或其他一些人可能觉得它很有用,因此对于ES6的新手来说,解构和扩展运算符的使用已被证明是非常有用的。

以下示例将使用for...of语句和.forEach方法。

实施例6,7和8可以与像任何官能环路被使用.map.filter.reduce.sort.every.some,有关这些方法的详细信息检查出数组对象

示例1:正常for...of循环 - 这里没有技巧。

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

示例2:将单词拆分为字符

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);

}

例3:用a key和。循环value

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type: 
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on internet explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

示例4:内联获取对象属性

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

示例5:获取所需内容的深层对象属性

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

实施例6:实施例3是否与.forEach

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

实施例7:实施例4是否与.forEach

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions 
// are required to be surrounded by parenthesis
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

实施例8:实施例5是否与.forEach

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});


ECMAScript5(Javascript上的版本)与Arrays一起使用。

forEach - 遍历数组中的每个项目,并为每个项目执行所需的任何操作。

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is the #" + (index+1) + " in musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

万一,对使用一些内置功能的阵列操作更感兴趣。

map - 它使用回调函数的结果创建一个新数组。当您需要格式化数组的元素时,可以使用此方法。

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

reduce - 正如名称所说,它通过调用传入currenct元素的给定函数和先前执行的结果将数组减少为单个值。

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

every - 如果数组中的所有元素都在回调函数中传递测试,则返回true或false。

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];  
ages.every(function(elem) {  
  return elem >= 18;
});

// Output: false

filter - 非常类似于除过滤器之外的每个过滤器返回一个数组,其中的元素返回true给定的函数。

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

希望这会有用。


lambda语法通常不适用于IE 10或更低版本。

我经常使用

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});


If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters

$("#ul>li").each(function(**index,value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

一些C风格的语言使用foreach循环遍历枚举。 在JavaScript中,这是通过for..in循环结构完成的

var index,
    value;
for (index in obj) {
    value = obj[index];
}

有一个问题。 for..infor..in每个对象的可枚举成员以及其原型上的成员。 要避免读取通过对象原型继承的值,只需检查属性是否属于该对象:

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

另外, ECMAScript 5已经向Array.prototype添加了一个forEach方法,该方法可用于使用calback枚举数组(polyfill在文档中,因此您仍然可以将它用于旧版浏览器):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

值得注意的是,当回调返回false时, Array.prototype.forEach不会中断。 jQueryUnderscore.jseach提供自己的变体,以提供可以短路的循环。


你可以打电话给每个人这样:

var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
    console.log("Index" + index);
    console.log("Element" + item);
})

element将具有从0到数组长度的每个索引的值。

输出:

let Array = [1,3,2];

theArray.forEach((element)=>{ 
  // use the element of the array
  console.log(element) 
}

阐释:

forEach是原型类。你也可以把它称为theArray.prototype.forEach(...);

原型:https://hackernoon.com/prototypes-in-javascript-5bba2990e04bhttps://hackernoon.com/prototypes-in-javascript-5bba2990e04b

您还可以像这样更改数组:

1    
3    
2

如果您正在使用jQuery库,则可以使用jQuery.each

$.each(yourArray, function(index, value) {
  // do your stuff here
});

编辑:

根据问题,用户想要javascript中的代码而不是jquery,所以编辑是

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}

如果要循环遍历数组,请使用标准的三部分for循环。

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

您可以通过缓存myArray.length或向后迭代来获得一些性能优化。


我还想将此作为反向循环的组合添加到上面,并为那些想要这种语法的人添加答案。

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

优点:

这样做的好处是:你已经在第一个中有了引用,就像以后不需要用另一行声明一样。循环通过对象数组时很方便。

缺点:

只要引用为false,这将会中断 - falsey(未定义等)。它可以作为一个优势使用。但是,它会使它更难阅读。而且,根据浏览器,它可以“不”优化,以比原始工作更快。


这是NON稀疏列表的迭代器,其中索引从0开始,这是处理document.getElementsByTagName或document.querySelectorAll时的典型场景。

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

用法示例:

示例#1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

例#2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

每个p标签都有 class="blue"

例#3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

每个其他p标签获得class="red">

例#4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

最后,前20个蓝色p标签变为绿色

使用字符串作为函数时的注意事项:该函数是在上下文中创建的,只应在您确定变量作用域的情况下使用。否则,最好传递范围更直观的函数。


jQuery方式使用$.map

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

可能for(i = 0; i < array.length; i++)循环不是最好的选择。为什么? 如果你有这个:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

该方法将调用从array[0]array[2]。首先,这将首先引用你甚至没有的变量,第二个你不会在数组中有变量,第三个会使代码更大胆。看这里,这是我使用的:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

如果你想让它成为一个函数,你可以这样做:

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

如果你想打破,更多的逻辑:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

例:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

它返回:

//Hello
//World
//!!!

如果你想使用forEach()它,它看起来像 -

theArray.forEach ( element => { console.log(element); });

如果你想使用for()它,它看起来像 -

for(let idx = 0; idx < theArray.length; idx++){ let element = theArray[idx]; console.log(element); }


如果你有一个庞大的阵列,你应该用它iterators来获得一些效率。迭代器是一定的JavaScript集合的性质(如MapSetStringArray)。甚至,for...of使用iterator引擎盖下。

迭代器通过让您一次一个地使用列表中的项目来提高效率,就像它们是流一样。使迭代器特殊的是它如何遍历集合。其他循环需要预先加载整个集合以便迭代它,而迭代器只需要知道集合中的当前位置。

您可以通过调用迭代器的next方法来访问当前项。下一个方法将返回value当前项的a和a,boolean以指示何时到达集合的末尾。以下是从数组创建迭代器的示例。

使用如下values()方法将常规数组转换为迭代器:

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

您还可以使用以下方法将常规数组转换为迭代器Symbol.iterator

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

您还可以将常规array转换为iterators以下内容:

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

注意

  • 迭代器本质上是可耗尽的。
  • iterable默认情况下不是对象。for..in在这种情况下使用,因为它不是值,而是与键一起使用。

你可以iteration protocol here阅读更多信息。


有三种实现方式foreachjQuery如下。

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3

没有内置的能力可以突破forEach。要中断执行,请使用Array#some以下内容:

[1,2,3].some(function(number) {
    return number === 1;
});

这是有效的,因为some只要以数组顺序执行的任何回调返回true,就会返回true,从而使其余的执行短路。原来的答案见阵原型some


for(let i=0;i<theArray.length;i++){
  console.log(i); //i will have the value of each index
}




iteration