Perbezaan: 1. forEach ialah iterator, yang bertanggungjawab untuk melintasi (Peta Set Tatasusunan) objek boleh lelar manakala untuk ialah mekanisme gelung, yang hanya boleh melintasi tatasusunan. 2. Sesetengah gelagat sampukan digunakan dalam gelung for, yang bagus untuk mengoptimumkan traversal tatasusunan dan carian Walau bagaimanapun, kerana forEach ialah lelaran dan hanya boleh dilalui mengikut urutan, ia tidak menyokong gelagat sampukan. 3. Titik permulaan gelung forEach hanya boleh 0, dan campur tangan manusia tidak boleh dilakukan tidak seperti gelung for, titik permulaan gelung boleh dikawal secara manual.
Persekitaran pengendalian tutorial ini: sistem Windows 7, ECMAScript versi 6, komputer Dell G3.
Perbezaan penting antara gelung dan forEach
for
Gelung ialah kaedah gelung yang telah wujud sejak js dicadangkan.
forEach
ialah kaedah yang dicadangkan oleh ES5 yang dipasang pada prototaip objek boleh lelar, seperti Array
Set
Map
.
forEach
ialah lelaran, bertanggungjawab untuk melintasi objek boleh lelaran.
Jadi apakah itu traversal , iterate dan objek lelaran masing-masing.
Traversal: merujuk kepada gelagat akses biasa dan sekali kepada setiap ahli struktur data.
Lelaran: Lelaran ialah bentuk pengulangan khas dan kaedah yang disediakan oleh iterator Secara lalai, ia adalah dalam susunan tertentu satu demi satuAkses ahli struktur data. Lelaran juga merupakan tingkah laku traversal.
Objek boleh lelar: Jenis iterable
diperkenalkan dalam ES6, Array
Set
Map
String
arguments
NodeList
ialah Kedua-duanya Milik iterable
, ciri mereka ialah kesemuanya mempunyai [Symbol.iterator]
kaedah, dan objek yang mengandunginya dianggap boleh lelar iterable
.
forEach
sebenarnya adalah lelaran Perbezaan penting antara gelung for
ialah forEach
bertanggungjawab untuk merentasi (Array
Set
Map
. ). Mengulang objek, dan gelung for
ialah mekanisme gelung yang hanya boleh melintasi tatasusunan.
Apakah itu iterator? Apabila ia dipanggil, ia akan menjana objek iterator (Objek Iterator Ia mempunyai kaedah .next()
dan setiap panggilan mengembalikan objek{value:value,done:Boolean}
). value
mengembalikan nilai pulangan selepas yield
Apabila yield
tamat, done
menjadi true
dan nilai dalaman diakses melalui panggilan berterusan dan lelaran berjujukan.
Iterator ialah objek khas. Simbolnya dalam spesifikasi ES6 ialah kaedah next()
yang mengembalikan objek, dan tingkah laku lelaran dinilai dalam done
. Iterator melaksanakan traversal tanpa mendedahkan perwakilan dalaman. Melihat pada kod
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}
kita nampak. Selagi ia adalah objek boleh lelar, memanggil Symbol.iterator
dalaman akan menyediakan lelaran, dan mengakses dalaman berdasarkan kaedah next
yang dikembalikan oleh lelaran Ini juga merupakan prinsip pelaksanaan for...of
.
let arr = [1, 2, 3, 4] for (const item of arr) { console.log(item); // 1 2 3 4 }
memanggil kaedah next
untuk mengembalikan nilai value
objek dan menyimpannya dalam item
sehingga value
terkeluar daripada gelung untuk undefined
dan semua objek boleh lelar adalah tersedia untuk for...of
Penggunaan. Mari kita lihat objek boleh lelaran yang lain:
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}
Jadi apabila sifat Symbol.iterator
dalam objek boleh lelaran dipanggil, ia boleh menjana lelaran dan forEach
juga menjana lelaran dalam panggil balik dalaman Nilai setiap elemen dihantar dalam fungsi
<span style="font-size: 20px;">for</span>
untuk gelung dan <span style="font-size: 20px;">forEach</span>
forEach
forEach
forEach
for
forEach
forEach
arr.forEach((self,index,arr) =>{},this)
diri:
indeks:
arr:
ini:
let arr = [1, 2, 3, 4]; arr.forEach(function (self, index, arr) { console.log(`当前元素为${self}索引为${index},属于数组${arr}`); }, person)
arr
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视频教程、编程视频】
Atas ialah kandungan terperinci Apakah perbezaan antara for dan foreach dalam es6. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!