ThoughtWorks西邮联合创新实验室

循环遍历数组的次数会受数组变化的影响吗?

2018-03-21  本文已影响55人  Gaarahan

在查看MDN文档中Array.prototype.filter()时,看到这样一段话:

The range of elements processed by filter() is set before the first invocation of callback. Elements which are appended to the array after the call to filter() begins will not be visited by callback. If existing elements of the array are changed, or deleted, their value as passed to callback will be the value at the time filter() visits them; elements that are deleted are not visited.


测试 1

var arr = [1,2,3];
var flag = 0;
arr.filter(function(val){
  if(flag == 0){      /*只在第一次循环时push一个新值 4 */
    arr.push(4);
    flag = 1;
  }
  console.log(val);    /*每次输出传给callback函数的元素*/
  console.log('当前数组:' + arr);    /*每次输出当前的数组*/
});

输出

image.png
可以看出,4虽然被加入到了数组中,但并未被访问

测试2

var arr = [1,2,3,4,5,6];
arr.filter(function(val,index){
  if(index == 3){ /*当访问到第4个元素时*/
    arr[4] = 10; /*修改数组的第5个元素*/
    arr.pop(); /*删除数组的最后一个元素*/
  }
  console.log('参数:' +val);
  console.log('当前数组:' + arr);
});
image.png
arr[4]被改变,访问到的值为改变后的值;
arr[5]被删除,因此没有被callback访问只进行了5次输出

验证后,突然想到,在循环遍历数组过程中,如果数组改变或增加,循环会不会遍历新加入的元素?

先看看简单的for循环

var arr = [1,2,3,4];
var flag = 0;
for(var i = 0; i < arr.length; i ++ ){
  if(flag == 0){
    arr.push(5);
    flag = 1;
  }
  console.log( arr[i] )
}
image.png

试试forEach()循环

var arr = [1,2,3,4];
var flag = 0;
arr.forEach(function(val){
  if(flag == 0){
    arr.push(5);
    flag = 1;
  }
  console.log( val )
});
console.log("arr : " + arr);
image.png

与filter()的描述相同,不过最后一句提到:

自己测试一下

MDN例子

var words = ['one', 'two', 'three', 'four'];
words.forEach(function(word) {
  console.log(word);
  if (word === 'two') {
      words.shift();
  }
});
console.log(words);
image.png
删除两个元素
var words = ['one', 'two', 'three', 'four','five'];
words.forEach(function(word) {
  console.log(word);
  if (word === 'two') {
      words.shift();
      words.shift();
  }
});
console.log(words);
image.png
简单对比可看出,删除了几个元素,就有几个当前元素后的元素被跳过,可以简单的理解为遍历时的参照为元素的下标,无论元素是否移动,下一个始终访问的是当前元素下标+1的元素
上一篇下一篇

猜你喜欢

热点阅读