如果再寫for循環(huán),我就。。。
點(diǎn)擊上方[全棧開發(fā)者社區(qū)]→右上角[...]→[設(shè)為星標(biāo)?
點(diǎn)擊領(lǐng)取全棧資料:全棧資料
for執(zhí)行最快,它沒有任何額外的函數(shù)調(diào)用棧和上下文。但在實(shí)際開發(fā)中我們要結(jié)合語義話、可讀性和程序性能,去選擇究竟使用哪種方案。下面來看for?,?foreach?,?map?,for...in?,?for...of五種方法現(xiàn)場battle。自我介紹
// 遍歷數(shù)組
let?arr = [1,2,3];
for(let?i =?0;i < arr.length;i++){
????console.log(i)?// 索引,數(shù)組下標(biāo)
????console.log(arr[i])?// 數(shù)組下標(biāo)所對(duì)應(yīng)的元素
}
// 遍歷對(duì)象
let?profile = {name:"April",nickname:"二十七刻",country:"China"};
for(let?i =?0, keys=Object.keys(profile); i < keys.length;i++){
????console.log(keys[i])?// 對(duì)象的鍵值
????console.log(profile[keys[i]])?// 對(duì)象的鍵對(duì)應(yīng)的值
}
// 遍歷字符串
let?str =?"abcdef";
for(let?i =?0;i < str.length ;i++){
????console.log(i)?// 索引 字符串的下標(biāo)
????console.log(str[i])?// 字符串下標(biāo)所對(duì)應(yīng)的元素
}
// 遍歷DOM 節(jié)點(diǎn)
let?articleParagraphs =?document.querySelectorAll('.article > p');
for(let?i =?0;i????articleParagraphs[i].classList.add("paragraph");
????// 給class名為“article”節(jié)點(diǎn)下的 p 標(biāo)簽添加一個(gè)名為“paragraph” class屬性。
}
forEach
// 遍歷數(shù)組
let?arr = [1,2,3];
arr.forEach(i?=>?console.log(i))
// logs 1
// logs 2
// logs 3
// 直接輸出了數(shù)組的元素
//遍歷對(duì)象
let?profile = {name:"April",nickname:"二十七刻",country:"China"};
let?keys =?Object.keys(profile);
keys.forEach(i?=>?{
????console.log(i)?// 對(duì)象的鍵值
????console.log(profile[i])?// 對(duì)象的鍵對(duì)應(yīng)的值
})
map
let?arr = [1,2,3,4,5];
let?res = arr.map(i?=>?i * i);
console.log(res)?// logs [1, 4, 9, 16, 25]
for...in枚舉
// 遍歷對(duì)象
let?profile = {name:"April",nickname:"二十七刻",country:"China"};
for(let?i?in?profile){
????let?item = profile[i];
????console.log(item)?// 對(duì)象的鍵值
????console.log(i)?// 對(duì)象的鍵對(duì)應(yīng)的值
// 遍歷數(shù)組
let?arr = ['a','b','c'];
for(let?i?in?arr){
????let?item = arr[i];
????console.log(item)?// 數(shù)組下標(biāo)所對(duì)應(yīng)的元素
????console.log(i)?// 索引,數(shù)組下標(biāo)
// 遍歷字符串
let?str =?"abcd"
for(let?i?in?str){
????let?item = str[i];
????console.log(item)?// 字符串下標(biāo)所對(duì)應(yīng)的元素
????console.log(i)?// 索引 字符串的下標(biāo)
}
for...of迭代
// 迭代數(shù)組數(shù)組
let?arr = ['a','b','c'];
for(let?item?of?arr){
????console.log(item)
}
// logs 'a'
// logs 'b'
// logs 'c'
// 迭代字符串
let?str =?"abc";
for?(let?value?of?str) {
????console.log(value);
}
// logs 'a'
// logs 'b'
// logs 'c'
// 迭代map
let?iterable =?new?Map([["a",?1], ["b",?2], ["c",?3]]
for?(let?entry?of?iterable) {
????console.log(entry);
}
// logs ["a", 1]
// logs ["b", 2]
// logs ["c", 3]
// 迭代map獲取鍵值
for?(let?[key, value]?of?iterable) {
????console.log(key)
????console.log(value);
}
// 迭代set
let?iterable =?new?Set([1,?1,?2,?2,?3,?3,4]);
for?(let?value?of?iterable) {
????console.log(value);
}
// logs 1
// logs 2
// logs 3
// logs 4
// 迭代 DOM 節(jié)點(diǎn)
let?articleParagraphs =?document.querySelectorAll('.article > p');
for?(let?paragraph?of?articleParagraphs) {
????paragraph.classList.add("paragraph");
????// 給class名為“article”節(jié)點(diǎn)下的 p 標(biāo)簽添加一個(gè)名為“paragraph” class屬性。
}
// 迭代arguments類數(shù)組對(duì)象
(function()?{
??for?(let?argument?of?arguments) {
????console.log(argument);
??}
})(1,?2,?3);
// logs:
// 1
// 2
// 3
// 迭代類型數(shù)組
let?typeArr =?new?Uint8Array([0x00,?0xff]);
for?(let?value?of?typeArr) {
??console.log(value);
}
// logs:
// 0
// 255
for語句是最原始的循環(huán)語句。定義一個(gè)變量i(數(shù)字類型,表示數(shù)組的下標(biāo)),按照一定的條件,對(duì)i進(jìn)行循環(huán)累加。條件通常為循環(huán)對(duì)象的長度,當(dāng)超過長度就停止循環(huán)。因?yàn)閷?duì)象無法判斷長度,所以搭配Object.keys()使用。forEach?ES5 提出。自稱是for語句的加強(qiáng)版,可以發(fā)現(xiàn)它比for語句在寫法上簡單了很多。但是本質(zhì)上也是數(shù)組的循環(huán)。forEach每個(gè)數(shù)組元素執(zhí)行一次 callback 函數(shù)。也就是調(diào)用它的數(shù)組,因此,不會(huì)改變原數(shù)組。返回值是undefine。map? ES5 提出。給原數(shù)組中的每個(gè)元素都按順序調(diào)用一次 ?callback 函數(shù)。生成一個(gè)新數(shù)組,不修改調(diào)用它的原數(shù)組本身。返回值是新的數(shù)組。for...in? ES5 提出。遍歷對(duì)象上的可枚舉屬性,包括原型對(duì)象上的屬性,且按任意順序進(jìn)行遍歷,也就是順序不固定。遍歷數(shù)組時(shí)把數(shù)組的下標(biāo)當(dāng)作鍵值,此時(shí)的i是個(gè)字符串型的。它是為遍歷對(duì)象屬性而構(gòu)建的,不建議與數(shù)組一起使用。for...of?ES6 提出。只遍歷可迭代對(duì)象的數(shù)據(jù)。
能力甄別
關(guān)于跳出循環(huán)體
break?與?continue。break語句是跳出當(dāng)前循環(huán),并執(zhí)行當(dāng)前循環(huán)之后的語句;continue語句是終止當(dāng)前循環(huán),并繼續(xù)執(zhí)行下一次循環(huán);
forEach?與map?是不支持跳出循環(huán)體的,其它三種方法均支持。forEach實(shí)現(xiàn)原理,就會(huì)理解這個(gè)問題。Array.prototype.forEach(callbackfn?[,thisArg]{
????
}
map()?同理。map()鏈?zhǔn)秸{(diào)用
map()?方法是可以鏈?zhǔn)秸{(diào)用的,這意味著它可以方便的結(jié)合其它方法一起使用。例如:reduce(),?sort(),?filter()?等。但是其它方法并不能做到這一點(diǎn)。forEach()的返回值是undefined,所以無法鏈?zhǔn)秸{(diào)用。// 將元素乘以本身,再進(jìn)行求和。
let?arr = [1,?2,?3,?4,?5];
let?res1 = arr.map(item?=>?item * item).reduce((total, value) =>?total + value);
console.log(res1)?// logs 55 undefined"
for...in會(huì)遍歷出原型對(duì)象上的屬性
Object.prototype.objCustom =?function()?{};
Array.prototype.arrCustom =?function()?{};
var?arr = ['a',?'b',?'c'];
arr.foo =?'hello
for (var i in arr) {
????console.log(i);
}
// logs
// 0
// 1
// 2
// foo
// arrCustom
// objCustom
hasOwnProperty()?方法,它會(huì)返回一個(gè)布爾值,指示對(duì)象自身屬性中是否具有指定的屬性(也就是,是否有指定的鍵)。如下:Object.prototype.objCustom =?function()?{};
Array.prototype.arrCustom =?function()?{};
var?arr = ['a',?'b',?'c'];
arr.foo =?'hello
for (var i in arr) {
????if (arr.hasOwnProperty(i)) {
????????console.log(i);
????}
}
// logs
// 0
// 1
// 2
// foo
// 可見數(shù)組本身的屬性還是無法擺脫。此時(shí)建議使用 forEach
for..in枚舉更方便;對(duì)于數(shù)組遍歷,如果不需要知道索引for..of迭代更合適,因?yàn)檫€可以中斷;如果需要知道索引,則forEach()更合適;對(duì)于其他字符串,類數(shù)組,類型數(shù)組的迭代,for..of更占上風(fēng)更勝一籌。但是注意低版本瀏覽器的是配性。性能
for?>?for-of?> forEach > map >?for-in
for?循環(huán)當(dāng)然是最簡單的,因?yàn)樗鼪]有任何額外的函數(shù)調(diào)用棧和上下文;for...of只要具有Iterator接口的數(shù)據(jù)結(jié)構(gòu),都可以使用它迭代成員。它直接讀取的是鍵值。forEach,因?yàn)樗鋵?shí)比我們想象得要復(fù)雜一些,它實(shí)際上是array.forEach(function(currentValue, index, arr), thisValue)它不是普通的 for 循環(huán)的語法糖,還有諸多參數(shù)和上下文需要在執(zhí)行的時(shí)候考慮進(jìn)來,這里可能拖慢性能;map()?最慢,因?yàn)樗姆祷刂凳且粋€(gè)等長的全新的數(shù)組,數(shù)組創(chuàng)建和賦值產(chǎn)生的性能開銷很大。for...in需要窮舉對(duì)象的所有屬性,包括自定義的添加的屬性也能遍歷到。且for...in的key是String類型,有轉(zhuǎn)換過程,開銷比較大。
總結(jié)
覺得本文對(duì)你有幫助?請(qǐng)分享給更多人
關(guān)注「全棧開發(fā)者社區(qū)」加星標(biāo),提升全棧技能
本公眾號(hào)會(huì)不定期給大家發(fā)福利,包括送書、學(xué)習(xí)資源等,敬請(qǐng)期待吧!
如果感覺推送內(nèi)容不錯(cuò),不妨右下角點(diǎn)個(gè)在看轉(zhuǎn)發(fā)朋友圈或收藏,感謝支持。
好文章,留言、點(diǎn)贊、在看和分享一條龍
評(píng)論
圖片
表情

