Home >Web Front-end >Front-end Q&A >What is the difference between for and foreach in es6
Difference: 1. forEach is an iterator, which is responsible for traversing (Array Set Map) iterable objects; while for is a loop mechanism, which can only traverse arrays. 2. Some interrupt behaviors are used in the for loop, which is good for optimizing array traversal and search. However, because forEach is an iterator and can only be traversed in order, it does not support interrupt behaviors. 3. The starting point of the forEach loop can only be 0, and human intervention is not possible; unlike the for loop, the starting point of the loop can be controlled manually.
The operating environment of this tutorial: Windows 7 system, ECMAScript version 6, Dell G3 computer.
The essential difference between for loop and forEach
for
Loop is a loop method that was introduced in js.
forEach
is a method proposed by ES5 and mounted on the prototype of an iterable object, such as Array
Set
Map
.
forEach
is an iterator, responsible for traversing iterable objects.
So what are traversal, iteration, iterable object respectively.
Traversal: refers to the regular and one-time access behavior to each member of the data structure.
Iteration: Iteration is a special form of recursion and a method provided by iterators. By default, it is in a certain orderone by oneAccess data structure members. Iteration is also a traversal behavior.
Iterable object: The iterable
type was introduced in ES6, Array
Set
Map
String
arguments
NodeList
all belong to iterable
, their characteristic is that they all have [Symbol.iterator]
method, the object containing it is considered an iterable iterable
.
forEach
is actually an iterator. The essential difference between it and the for
loop is that forEach
is responsible for traversing (Array
Set
Map
) Iterable object, and for
loop is a loop mechanism, which can only traverse the array .
What is an iterator? When it is called, an iterator object (Iterator Object) will be generated. It has a .next()
method. Each This call returns an object {value:value,done:Boolean}
, value
returns the return value after yield
, when yield
End, done
becomes true
, and the internal value is accessed through continuous calls and sequential iterations.
Iterator is a special object. Its symbol in the ES6 specification is the next()
method of the returned object, and the iteration behavior is judged in done
. Iterators implement traversal without exposing the internal representation. Looking at the code
let arr = [1, 2, 3, 4] // 可迭代对象 let iterator = arr[Symbol.iterator]() // 调用 Symbol.iterator 后生成了迭代器对象 console.log(iterator.next()); // {value: 1, done: false} 访问迭代器对象的next方法 console.log(iterator.next()); // {value: 2, done: false} console.log(iterator.next()); // {value: 3, done: false} console.log(iterator.next()); // {value: 4, done: false} console.log(iterator.next()); // {value: undefined, done: true}
we see. As long as it is an iterable object, calling the internal Symbol.iterator
will provide an iterator, and access the internals based on the next
method returned by the iterator, which is also for.. The implementation principle of .of
.
let arr = [1, 2, 3, 4] for (const item of arr) { console.log(item); // 1 2 3 4 }
Call the next
method to return the value
value of the object and save it in item
until value
is undefined
Break out of the loop and all iterable objects are available for for...of
consumption. Let’s look at other iterable objects:
function num(params) { console.log(arguments); // Arguments(6) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ] let iterator = arguments[Symbol.iterator]() console.log(iterator.next()); // {value: 1, done: false} console.log(iterator.next()); // {value: 2, done: false} console.log(iterator.next()); // {value: 3, done: false} console.log(iterator.next()); // {value: 4, done: false} console.log(iterator.next()); // {value: undefined, done: true} } num(1, 2, 3, 4) let set = new Set('1234') set.forEach(item => { console.log(item); // 1 2 3 4 }) let iterator = set[Symbol.iterator]() console.log(iterator.next()); // {value: 1, done: false} console.log(iterator.next()); // {value: 2, done: false} console.log(iterator.next()); // {value: 3, done: false} console.log(iterator.next()); // {value: 4, done: false} console.log(iterator.next()); // {value: undefined, done: true}
So the Symbol.iterator
property in the iterable object can generate an iterator when it is called, and forEach
is also generated An iterator that passes out the value of each element in the inner callback function
<span style="font-size: 20px;">for</span>
loop and <span style="font-size: 20px;">forEach</span>
.
interrupt.
Delete its own element, and the index cannot be reset.
Loops can control the starting point of the loop.
parameters of forEach
? It probably looks like this: <pre class="brush:php;toolbar:false">arr.forEach((self,index,arr) =>{},this)</pre>
let arr = [1, 2, 3, 4]; arr.forEach(function (self, index, arr) { console.log(`当前元素为${self}索引为${index},属于数组${arr}`); }, person)###We can use ###arr### to achieve array deduplication: ###
let arr1 = [1, 2, 1, 3, 1]; let arr2 = []; arr1.forEach(function (self, index, arr) { arr.indexOf(self) === index ? arr2.push(self) : null; }); console.log(arr2); // [1,2,3]
forEach
的中断在js中有break
return
continue
对函数进行中断或跳出循环的操作,我们在 for
循环中会用到一些中断行为,对于优化数组遍历查找是很好的,但由于forEach
属于迭代器,只能按序依次遍历完成,所以不支持上述的中断行为。
let arr = [1, 2, 3, 4], i = 0, length = arr.length; for (; i < length; i++) { console.log(arr[i]); //1,2 if (arr[i] === 2) { break; }; }; arr.forEach((self,index) => { console.log(self); if (self === 2) { break; //报错 }; }); arr.forEach((self,index) => { console.log(self); if (self === 2) { continue; //报错 }; });
如果我一定要在 forEach
中跳出循环呢?其实是有办法的,借助try/catch
:
try { var arr = [1, 2, 3, 4]; arr.forEach(function (item, index) { //跳出条件 if (item === 3) { throw new Error("LoopTerminates"); } //do something console.log(item); }); } catch (e) { if (e.message !== "LoopTerminates") throw e; };
若遇到 return
并不会报错,但是不会生效
let arr = [1, 2, 3, 4]; function find(array, num) { array.forEach((self, index) => { if (self === num) { return index; }; }); }; let index = find(arr, 2);// undefined
forEach
删除自身元素,index不可被重置在 forEach
中我们无法控制 index
的值,它只会无脑的自增直至大于数组的 length
跳出循环。所以也无法删除自身进行index
重置,先看一个简单例子:
let arr = [1,2,3,4] arr.forEach((item, index) => { console.log(item); // 1 2 3 4 index++; });
index
不会随着函数体内部对它的增减而发生变化。在实际开发中,遍历数组同时删除某项的操作十分常见,在使用forEach
删除时要注意。
for
循环可以控制循环起点如上文提到的 forEach
的循环起点只能为0不能进行人为干预,而for
循环不同:
let arr = [1, 2, 3, 4], i = 1, length = arr.length; for (; i < length; i++) { console.log(arr[i]) // 2 3 4 };
那之前的数组遍历并删除滋生的操作就可以写成
let arr = [1, 2, 1], i = 0, length = arr.length; for (; i < length; i++) { // 删除数组中所有的1 if (arr[i] === 1) { arr.splice(i, 1); //重置i,否则i会跳一位 i--; }; }; console.log(arr); // [2] //等价于 var arr1 = arr.filter(index => index !== 1); console.log(arr1) // [2]
<span style="font-size: 18px;">for</span>
循环和<span style="font-size: 18px;">forEach</span>
的性能区别
在性能对比方面我们加入一个 map
迭代器,它与 filter
一样都是生成新数组。
对比 for
forEach
map
的性能在浏览器环境中都是什么样的:
性能比较:for > forEach > map 在chrome 62 和 Node.js v9.1.0环境下:for
循环比 forEach
快1倍,forEach
比 map
快20%左右。
原因分析for
:for循环没有额外的函数调用栈和上下文,所以它的实现最为简单。
forEach
:对于forEach来说,它的函数签名中包含了参数和上下文,所以性能会低于 for
循环。
map
:map
最慢的原因是因为 map
会返回一个新的数组,数组的创建和赋值会导致分配内存空间,因此会带来较大的性能开销。
如果将map
嵌套在一个循环中,便会带来更多不必要的内存消耗。
当大家使用迭代器遍历一个数组时,如果不需要返回一个新数组却使用 map
是违背设计初衷的。
【相关推荐:javascript视频教程、编程视频】
The above is the detailed content of What is the difference between for and foreach in es6. For more information, please follow other related articles on the PHP Chinese website!