目錄
forEach 的中断
forEach 删除自身元素,index不可被重置
for 循环可以控制循环起点
首頁 web前端 前端問答 es6中for和foreach的差別是什麼

es6中for和foreach的差別是什麼

Oct 21, 2022 pm 05:32 PM
javascript es6 es6數組

區別:1、forEach是一個迭代器,是負責遍歷(Array Set Map)可迭代物件的;而for是一種循環機制,只是能透過它遍歷出數組。 2.for循環中會用到一些中斷行為,對於優化數組遍歷查找是很好的,但由於forEach屬於迭代器,只能按序依次遍歷完成,所以不支援中斷行為。 3.forEach的循環起點只能為0,且不能進行人為幹預;而for循環不同,可以人為控制循環起點。

es6中for和foreach的差別是什麼

本教學操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。

for迴圈和forEach本質差異

#for迴圈是js提出時就有的迴圈方法。

forEach是ES5提出的,掛載在可迭代物件原型上的方法,例如Array Set Map

forEach是一個迭代器,負責遍歷可迭代物件。

那麼遍歷迭代可迭代物件分別是什麼呢。

  • 遍歷:指的對資料結構的每一個成員進行有規律的且為一次存取的行為。

  • 迭代:迭代是遞歸的特殊形式,是迭代器提供的一種方法,預設是依照一定順序逐一存取資料結構成員。迭代也是一種遍歷行為。

  • 可迭代物件:ES6中引入了iterable 類型,Array Set Map String arguments NodeList 都屬於iterable,他們特質就是都擁有[Symbol.iterator] 方法,包含他的物件被認為是可迭代的iterable

forEach 其實是一個迭代器,他與for 迴圈本質上的差別是forEach 是負責遍歷(Array Set Map)可迭代物件的,而for 迴圈是一種循環機制,只是能透過它遍歷出數組。

什麼是迭代器,當它被呼叫時就會產生一個迭代器物件(Iterator Object),它有一個.next()方法,每次呼叫傳回一個物件{value:value,done:Boolean}value傳回的是yield 後的回傳值,當yield 結束,done 變成true,透過不斷呼叫並依序的迭代存取內部的值。

迭代器是一種特殊物件。 ES6規範中它的標誌是傳回物件的 next() 方法,迭代行為判斷在 done 之中。在不暴露內部表示的情況下,迭代器實現了遍歷。看程式碼

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}
登入後複製

我們看到了。只要是可迭代對象,呼叫內部的Symbol.iterator 都會提供一個迭代器,並根據迭代器返回的next 方法來存取內部,這也是for.. .of 的實作原理。

let arr = [1, 2, 3, 4]
for (const item of arr) {
    console.log(item); // 1 2 3 4 
}
登入後複製

把呼叫next 方法傳回物件的value 值並儲存在item 中,直到valueundefined 跳出循環,所有可迭代物件可供for...of消費。再來看看其他可迭代物件:

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}
登入後複製

所以可迭代物件中的Symbol.iterator 屬性被呼叫時都能產生迭代器,而forEach 也是生成一個迭代器,在內部的回呼函數中傳遞出每個元素的值

<span style="font-size: 20px;">#for</span>##循環和<span style="font-size: 20px;"></span>#forEach的語法差異

了解了本質差異,在應用過程中,他們到底有什麼語法差異呢?
  • forEach

    的參數。
  • forEach

    的中斷。
  • forEach

    刪除自身元素,index無法重設。
  • for

    迴圈可以控制迴圈起點。

forEach 的參數

我們真正了解 forEach

的完整傳參內容嗎?它大概是這樣:
    arr.forEach((self,index,arr) =>{},this)
    登入後複製
  • self:

    陣列目前遍歷的元素,預設從左往右依序取得陣列元素。
  • index:

    陣列目前元素的索引,第一個元素索引為0,依序類別推。
  • arr:

    目前遍歷的陣列。
  • this:

    回呼函數中this指向。
  • 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倍,forEachmap 快20%左右。

    原因分析for:for循环没有额外的函数调用栈和上下文,所以它的实现最为简单。

    forEach:对于forEach来说,它的函数签名中包含了参数和上下文,所以性能会低于 for 循环。

    mapmap 最慢的原因是因为 map 会返回一个新的数组,数组的创建和赋值会导致分配内存空间,因此会带来较大的性能开销。

    如果将map嵌套在一个循环中,便会带来更多不必要的内存消耗。

    当大家使用迭代器遍历一个数组时,如果不需要返回一个新数组却使用 map 是违背设计初衷的。

    【相关推荐:javascript视频教程编程视频

    以上是es6中for和foreach的差別是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳圖形設置
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您聽不到任何人,如何修復音頻
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    WWE 2K25:如何解鎖Myrise中的所有內容
    4 週前 By 尊渡假赌尊渡假赌尊渡假赌

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

    如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

    WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

    WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

    如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

    如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

    如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

    如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

    JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

    JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

    javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

    用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

    簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

    JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

    如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

    JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

    See all articles