|
| 1 | +与for循环一样,forEach也属于完整遍历数组的方法,并会对数组每项元素执行提供的回调函数,一个完整的forEach应该是这样,我们一一解释回调函数的参数,与后方的this有何作用。 |
| 2 | + |
| 3 | +arr.forEach(function(self,index,arr){},this); |
| 4 | + |
| 5 | +self:数组当前遍历的元素,默认从左往右依次获取数组元素。 |
| 6 | + |
| 7 | +index:数组当前元素的索引,第一个元素索引为0,依次类推。 |
| 8 | + |
| 9 | +arr:当前遍历的数组。 |
| 10 | + |
| 11 | +this:回调函数中this指向。 |
| 12 | + |
| 13 | +我们来看个简单的forEach例子,加强对于这四个参数的印象: |
| 14 | + |
| 15 | + |
| 16 | +// code |
| 17 | + |
| 18 | +let arr1 = [1, 2, 3, 4]; |
| 19 | +let obj = { |
| 20 | + a: 1 |
| 21 | +}; |
| 22 | +arr1.forEach(function (self, index, arr) { |
| 23 | + console.log(`当前元素为${self}索引为${index},属于数组${arr}`); |
| 24 | + //做个简单计算 |
| 25 | + console.log(self + this.a); |
| 26 | +}, obj) |
| 27 | + |
| 28 | +1.forEach不支持break |
| 29 | + |
| 30 | +大家都知道,在使用for循环时可以使用break跳出循环,比如我希望找到数组中符合条件的第一个元素就跳出循环,这对于优化数组遍历是非常棒的。很遗憾,forEach并不支持break操作,使用break会导致报错。 |
| 31 | + |
| 32 | +// code |
| 33 | + |
| 34 | +let arr = [1, 2, 3, 4], |
| 35 | + i = 0, |
| 36 | + length = arr.length; |
| 37 | +for (; i < length; i++) { |
| 38 | + console.log(arr[i]); //1,2 |
| 39 | + if (arr[i] === 2) { |
| 40 | + break; |
| 41 | + }; |
| 42 | +}; |
| 43 | + |
| 44 | +arr.forEach((self,index) => { |
| 45 | + console.log(self); |
| 46 | + if (self === 2) { |
| 47 | + break; //报错 |
| 48 | + }; |
| 49 | +}); |
| 50 | + |
| 51 | + |
| 52 | + |
| 53 | +那forEach能不能跳出循环呢?可以,不过不是使用break,而是结合try catch操作,有兴趣可是看看博主这篇文章 js forEach跳出循环 |
| 54 | + |
| 55 | +2.forEach中使用return无效 |
| 56 | + |
| 57 | +首先需要确定的,直接再for循环中使用return会报错(函数中使用for可以return),forEach中使用return不会报错,但rerutn并不会生效,我们来看个例子: |
| 58 | + |
| 59 | + |
| 60 | +// code |
| 61 | + |
| 62 | +let arr = [1, 2, 3, 4]; |
| 63 | + |
| 64 | +function find(array, num) { |
| 65 | + array.forEach((self, index) => { |
| 66 | + if (self === num) { |
| 67 | + return index; |
| 68 | + }; |
| 69 | + }); |
| 70 | +}; |
| 71 | +let index = find(arr, 2);// undefined |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +上述代码想要找到数字2在数组中的索引,但return并不会起到终止代码运行并返回值的作用。 |
| 76 | +当然如果我们真的要用return返回某个值,那就只能将return操作放在函数中,而不是forEach循环中,像这样: |
| 77 | + |
| 78 | +// code |
| 79 | + |
| 80 | +function find(array, num) { |
| 81 | + let _index; |
| 82 | + array.forEach((self, index) => { |
| 83 | + if (self === num) { |
| 84 | + _index = index; |
| 85 | + }; |
| 86 | + }); |
| 87 | + return _index; |
| 88 | +}; |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | + |
| 93 | +3.forEach删除自身元素index不会被重置 |
| 94 | +还记得文章开头的问题吗,那段代码其实只会执行一次,数组也不会被删除干净,这是因为forEach在遍历跑完回调函数后,会隐性让index自增,像这样: |
| 95 | + |
| 96 | +// code |
| 97 | + |
| 98 | +arr.forEach((item, index) => { |
| 99 | + arr.splice(index, 1); |
| 100 | + console.log(1); |
| 101 | + //这里隐性让index自增加1 |
| 102 | + index++; |
| 103 | +}); |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | +当第一次遍历结束,此时数组为[2]而index变成了1,此时数组最大索引只是0,不满足条件,所以跳出了循环。 |
| 109 | +灵机一动,有没有什么办法让此时的forEach不跳出循环呢,当然有,使用ES6的拓展运算符。 |
| 110 | +// code |
| 111 | + |
| 112 | +[...arr].forEach((item, index) => { |
| 113 | + arr.splice(index, 1); |
| 114 | + console.log(1); |
| 115 | +}); |
| 116 | + |
| 117 | +通过拓展运算符重置数组arr,达到不跳出循环的目的,你会发现内部确实执行了两次,很遗憾的是index依旧没被重置,所以数组arr还是无法在遍历的同时删空自己。 |
| 118 | +因为在实际开发中,遍历数组同时删除某项的操作十分常见,所以对于习惯了forEach的同学,这一点一定要注意。 |
| 119 | + |
| 120 | + |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | + |
| 125 | + |
0 commit comments