首頁 web前端 前端問答 es6的for of可以遍歷對象嗎

es6的for of可以遍歷對象嗎

May 19, 2022 pm 04:11 PM
es6

es6的「for of」不能遍歷物件。原因:ES6中引入了Iterator接口,只有提供了Iterator接口的資料類型才可以使用“for-of”來循環遍歷;而普通對象默認沒有提供Iterator接口,因此無法用“for-of”來進行遍歷。

es6的for of可以遍歷對象嗎

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

隨著前端的不斷發展,光循環就出現了好多種方法,for、forEach、do..while、for...in等等,不過這些循環也都各有各的應用場景和優缺點。

ES6又為我們提供了新的循環方法for...of,它可以循環字串、數組及其他類數組對象,那作為最普遍存在的Object對象,按理,可以循環?

我們來看看下方的程式碼範例:

{
    // 迭代数组
  const iterable = ['a', 'b'];
  for (const value of iterable) {
    console.log(value);
  }
  // output: a b
}
{
    // 普通对象
    const obj = {
      a: 'A',
      b: 'B'
    }
    for(const item of obj){
      console.log(item)
    }
    // Uncaught TypeError: obj is not iterable
}
登入後複製

oh no,報錯了:Uncaught TypeError: obj is not iterable。提示obj是不可迭代的,顯然直接用for...of去遍歷Object物件是不行的。

那麼可以遍歷大部分資料結構的for...of為何不能遍歷Object物件?

原因:

ES6 中引入了Iterator,只有提供了Iterator 介面的資料類型才可以使用for-of 來循環遍歷,而Array、 Set、Map、某些類別數組如arguments 等資料類型都預設提供了Iterator 接口,所以它們可以使用for-of 來進行遍歷。

而對於普通的對象,for...of結構不能直接使用,會報錯,提示obj is not iterable,也就是說普通對象預設沒有Iterator接口,必須部署了Iterator 介面後才能使用。

怎麼解決?讓for-of 遍歷物件

那麼原因清楚了,該怎麼解決呢?能不能為物件已經其它的一些資料型別提供Iterator 介面呢

答案是可以的,ES6 同時提供了Symbol.iterator 屬性,只要一個資料結構有這個屬性,就會被視為有Iterator 介面,接著就是如何實現這個介面了,如下就是一個最簡實作:

newObj[Symbol.iterator] = function(){
    let index = 0
        , self = this
        , keys = Object.keys( self )
        ;
    
    return {
        next(){
            if( index < keys.length ){
                return {
                    value: self[keys[index++]]
                    , done: false
                };
            }
            else{
                return {
                    value: undefined
                    , done: true
                }
            }
        }
    };
};
登入後複製

仔細看一下發現就會發現 Symbol.iterator 介面其實是一個 Generator 函數,那麼就可以簡化程式碼:

newObj[Symbol.iterator] = function* (){
    let keys = Object.keys( this )
        ;
    
    for(let i = 0, l = keys.length; i < l; i++){
        yield this[keys[i]];
    }
}

for(let v of newObj){
    console.log( v );
}
// 输出结果
// 5
// 6
登入後複製

值得注意的是 Object.keys 碰巧解決了先前 for-in 遇到的繼承問題

這樣滿足了我們的期望,使用 for-of 來遍歷對象,但是好像哪裡不對,我們遍歷對象時一般都是期望同時輸出 key 和 value 的,這樣調整程式碼

newObj[Symbol.iterator] = function* (){
    let keys = Object.keys( this )
        ;
    
    for(let i = 0, l = keys.length; i < l; i++){
        yield {
            key: keys[i]
            , value: this[keys[i]]
        };
    }
}

for(let v of newObj){
    console.log( v );
}
// 输出结果
// {key: "e", value: 5}
// {key: "f", value: 6}
登入後複製

這樣回傳了一個對象,似乎又很不舒服,我們能不能嘗試一些解構賦值呢。 。 。

for(let {key, value} of newObj){
    console.log(key, value );
}
// 输出结果
// e 5
// f 6
登入後複製

這樣似乎非常完美了。 。 。

擴充知識:for-of和其他迴圈的差異

#迴圈名稱 迴圈物件 是否可中斷迴圈 是否有回傳值
for for循環體的length 可以 無回傳值
forEach 僅可循環陣列、map、set等,不可循環字串、普通物件 不可以 無回傳值
do...while 滿足某種條件,則可一直循環,至少循環一次 可以 無回傳值
while #滿足某種條件,則可一直循環 可以 無回傳值
map 組成新的陣列成員,僅可循環數組,不可循環字串、普通對象,set 、map 不可中斷 傳回新數組,不影響原始數組
filter 過濾數組成員,僅可循環數組,不可循環字串、普通對象,set、map 不可中斷 傳回新數組,不影響原始數組
for...in 可循環陣列、物件,不可循環map、set。可遍歷數字鍵名,還可遍歷手動添加的其他鍵,甚至包括原型鏈上的鍵 可以 無回傳值
for...of 循環可迭代的對象,不可循環普通對象(統一資料結構遍歷) 可以 無回傳值

【相關推薦:javascript影片教學web前端

以上是es6的for of可以遍歷對象嗎的詳細內容。更多資訊請關注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脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

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

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

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

async是es6還是es7的 async是es6還是es7的 Jan 29, 2023 pm 05:36 PM

async是es7的。 async和await是ES7中新增內容,是對於非同步操作的解決方案;async/await可以說是co模組和生成器函數的語法糖,用更清晰的語意解決js非同步程式碼。 async顧名思義是「非同步」的意思,async用於聲明一個函數是異步的;async和await有一個嚴格規定,兩者都離不開對方,且await只能寫在async函數中。

ES6怎麼求數組反轉 ES6怎麼求數組反轉 Oct 26, 2022 pm 06:19 PM

在ES6中,可以利用數組物件的reverse()方法來實現數組反轉,該方法用於顛倒數組中元素的順序,將最後一個元素放在第一位,而第一個元素放在最後,語法「array.reverse()」。 reverse()方法會修改原始數組,如果不想修改需要配合擴充運算子「...」使用,語法「[...array].reverse()」。

小程式為什麼要將es6轉es5 小程式為什麼要將es6轉es5 Nov 21, 2022 pm 06:15 PM

為了瀏覽器相容。 ES6作為JS的新規範,加入了許多新的語法和API,但現代瀏覽器對ES6新特性支援不高,所以需將ES6程式碼轉換為ES5程式碼。在微信web開發者工具中,會預設使用babel將開發者ES6語法程式碼轉換為三端都能很好支援的ES5的程式碼,幫助開發者解決環境不同所帶來的開發問題;只需要在專案中配置勾選好「ES6轉ES5」選項即可。

es6怎麼找出2個數組中不同項 es6怎麼找出2個數組中不同項 Nov 01, 2022 pm 06:07 PM

步驟:1、將兩個陣列分別轉換為set類型,語法「newA=new Set(a);newB=new Set(b);」;2、利用has()和filter()求差集,語法“ new Set([...newA].filter(x =>!newB.has(x)))”,差集元素會被包含在一個set集合中返回;3、利用Array.from將集合轉為數組類型,語法“Array.from(集合)”。

es5和es6怎麼實現陣列去重 es5和es6怎麼實現陣列去重 Jan 16, 2023 pm 05:09 PM

es5中可以利用for語句和indexOf()函數來實現數組去重,語法“for(i=0;i<數組長度;i++){a=newArr.indexOf(arr[i]);if(a== -1){...}}」。在es6中可以利用擴充運算子、Array.from()和Set來去重;需要先將陣列轉為Set物件來去重,然後利用擴充運算子或Array.from()函數來將Set物件轉回數組即可。

es6暫時性死區是什麼意思 es6暫時性死區是什麼意思 Jan 03, 2023 pm 03:56 PM

在es6中,暫時性死區是語法錯誤,是指let和const命令使區塊形成封閉的作用域。在程式碼區塊內,使用let/const指令宣告變數之前,變數都是不可用的,在變數宣告之前屬於該變數的「死區」;這在語法上,稱為「暫時性死區」。 ES6規定暫時性死區和let、const語句不出現變量提升,主要是為了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行為。

require是es6語法嗎 require是es6語法嗎 Oct 21, 2022 pm 04:09 PM

不是,require是CommonJS規範的模組化語法;而es6規範的模組化語法是import。 require是運行時加載,import是編譯時加載;require可以寫在程式碼的任意位置,import只能寫在文件的最頂端且不可在條件語句或函數作用域中使用;require運行時才引入模組的屬性所以效能相對較低,import編譯時引入模組的屬性所所以效能稍高。

es6怎麼判斷陣列裡總共有多少項 es6怎麼判斷陣列裡總共有多少項 Jan 18, 2023 pm 07:22 PM

在es6中,可以利用array物件的length屬性來判斷數組裡總共有多少項,即取得數組中元素的個數;該屬性可傳回數組中元素的數組,只需要使用「array.length」語句即可傳回表示數組物件的元素個數的數值,也就是長度值。

See all articles