你真的了解for in和for of嗎辅鲸?

今天有個朋友跟我說了一下之前發(fā)的文章當(dāng)中統(tǒng)計字符串出現(xiàn)的次數(shù)格郁,for in其實可以用for of代替,因為沒有使用下標(biāo)的必要独悴,剛開始的時候例书,我還真不知道這兩個到底有什么區(qū)別,于是我便決定去研究了一番刻炒。决采。。結(jié)果讓我又漲知識了~

談?wù)刦or in

我們平常遍歷數(shù)組可能最常用的就是for循環(huán)坟奥,其次就是forEach树瞭,map,filter爱谁,some晒喷,every等等方法,只是這些方法的返回值不一樣访敌。forEach更沒有返回值凉敲,使用break不能中斷循環(huán),return也不能返回到外層函數(shù)。其實for in也可以用來遍歷數(shù)組荡陷。

let arr = [1,2,3];
for(let i in arr){
  console.log(i, '--------', arr[i]);
}

上面可以打印出arr的每一個元素以及索引:

perfect雨效!你是不是以為這樣挺完美的?那么問題來了废赞,如果有人偷偷在Object的原型對象和Array的原型對象上添加一些方法,或者給數(shù)組添加一些其他屬性叮姑,看看會發(fā)生什么情況:

Object.prototype.objMethod = function () {};
Array.prototype.arrMethod = function () {};
let arr = [1,2,3];
arr.attr = 'hi';
for(let i in arr){
  console.log(i, '---------', arr[i]);
}

打印結(jié)果如下:

天吶唉地!居然把原型對象上的方法和自己給數(shù)組添加的屬性全都遍歷出來了。這可不是我們想要的結(jié)果传透,為什么會這樣呢耘沼?
MDN對for in的用法定義為:以任意順序遍歷一個對象的除[Symbol]以外的可枚舉屬性。
我們來簡單抓一下重點朱盐,理解一下這句話:
1.任意順序遍歷
也就是說for in遍歷數(shù)組對象是無法保證將按照數(shù)組的索引順序來訪問數(shù)組的屬性的群嗤。
舉個例子:

let arr = [];
arr[2] = 'c';
arr[1] = 'b';
arr[0] = 'a';
for(let i in arr){
  console.log(i, '--------', arr[i]);
}

在IE8及以下版本中,會打印出:'2' -------- 'c', '1' -------- 'b', '0' -------- 'a'兵琳。這是不是很扯淡狂秘。。躯肌。
我再舉個例子:

let arr = [];
arr[5] = 10;
for(let i in arr){
  console.log(i, '--------', arr[i]);
}

打印結(jié)果如下:

如果用普通for循環(huán)或者for of遍歷的話者春,打印結(jié)果如下:
通過兩者比較可以看到for in僅僅只顯示顯示設(shè)置的索引5和對應(yīng)的值,忽略了0-4的顯示清女,而for of卻會全部顯示出來钱烟。

·
2.可枚舉屬性
什么是可枚舉屬性呢?
在js的每個對象的屬性都有一個叫enumerable的屬性嫡丙,(什么拴袭?你問我屬性也有屬性嗎?當(dāng)然啦曙博!萬物皆對象嘛~ 對象的屬性當(dāng)然也是對象啦~)這個屬性的true和false決定了這個屬性是否可以枚舉(就是讓一些方法訪問到這個屬性)拥刻,那么常見的有兩種,第一就是js基本包裝類型自帶的原型屬性不可枚舉羊瘩,如Object泰佳,Array等;第二就是通過Object.defineProperty()方法指定enumeralbe為false的屬性不可枚舉尘吗。
而通過prototype添加的屬性和方法默認是可枚舉的(ES5之前不能定義為不可枚舉)逝她,其實這也就能說得通為什么for in能遍歷到原型對象上的方法,而不能遍歷到Object或Array內(nèi)部的方法了睬捶。

for in由于歷史遺留問題黔宛,它遍歷的實際上是對象的屬性名稱。一個Array數(shù)組實際上也是一個對象擒贸,它的每一個元素索引都被視為一個屬性臀晃。

總結(jié)一下用for in 遍歷數(shù)組的缺點:
1.遍歷順序在某些情況下觉渴,可能不是按照實際數(shù)組的內(nèi)部順序。
2.它會遍歷數(shù)組的所有可枚舉屬性徽惋,包括原型對象上的屬性案淋。
3.遍歷的索引是字符串型的數(shù)字,而不是數(shù)字型的险绘,所以不能夠直接進行幾何運算踢京。(仔細觀察上面for in的打印結(jié)果,i打印出來的顏色是黑色的宦棺,這是字符串型才有的特征瓣距,而數(shù)字型打印出來的顏色應(yīng)該是藍色的。)

看來for in貌似不太適合用來遍歷數(shù)組啊代咸,那怎么解決呢蹈丸?for of就誕生了!

談?wù)刦or of

我們使用for of遍歷數(shù)組則完全避免了上述的一些問題呐芥。
簡單來說逻杖,它可以直接獲取到數(shù)組的值,只會遍歷數(shù)組本身的元素贩耐,即使你在原型對象上添加了方法或自己添加了屬性弧腥。

Object.prototype.objMethod = function () {};
Array.prototype.arrMethod = function () {};
let arr = [1,2,3];
arr.attr = 'hi';
for(let val of arr){
  console.log(val);
}

打印結(jié)果如下:

你看,被人偷偷在原型對象上加上的方法和給數(shù)組添加的屬性都沒有顯示出來了潮太!這是因為原型鏈上的對象并沒有默認部署遍歷器生成方法管搪。

MDN對for of的用法定義為:在可迭代對象(包括Array,Map,Set,String,TypedArray,arguments對象等等)上創(chuàng)建一個迭代循環(huán),調(diào)用自定義迭代器铡买,并為每一個不同屬性的值執(zhí)行語句
是不是又很抽象更鲁?我們再來解釋一下這句話:
1.可迭代,迭代器
其實奇钞,在js中Array澡为,Map等數(shù)據(jù)結(jié)構(gòu)都存在著一個叫做迭代器(Iterator)的東西,它是一種接口景埃,為各種不同的數(shù)據(jù)結(jié)構(gòu)提供統(tǒng)一的訪問機制媒至,任何數(shù)據(jù)結(jié)構(gòu)只要有這個接口,就可以完成遍歷操作谷徙,這個迭代器的作用有三個:一是為各種數(shù)據(jù)結(jié)構(gòu)拒啰,提供一個統(tǒng)一的、簡便的訪問接口完慧;二是使得數(shù)據(jù)結(jié)構(gòu)的成員能夠按某種次序排列谋旦;三是 ES6 創(chuàng)造了一種新的遍歷命令for...of循環(huán),Iterator 接口主要供for...of消費。
那么如果我們用for of來遍歷對象呢册着?

let obj = {
  uname: 'pink',
  age: 18,
  sex: '男'
}
for (let val of obj) {
  console.log(val);
}

打印一下:

What?直接報錯了拴孤!這是為啥呢?
其實對象(Object)這種數(shù)據(jù)結(jié)構(gòu)是沒有默認的Iterator接口的甲捏,需要自己部署這個迭代器演熟,才會被for of循環(huán)遍歷。對象(Object)之所以沒有默認部署Iterator接口司顿,是因為對象的哪一個屬性先遍歷绽媒,哪一個屬性后遍歷是不確定的。

總結(jié)

for of適用于遍歷數(shù)組免猾,字符串,map囤热,set等擁有迭代器的對象的集合猎提,但是不能遍歷對象,因為沒有迭代器旁蔼。
for in主要是為遍歷對象而設(shè)計的锨苏,不適用于遍歷數(shù)組。它最常用的地方應(yīng)該是用于調(diào)試棺聊,可以更方便的去檢查對象的屬性伞租。

文中如有錯誤之處歡迎指正~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市限佩,隨后出現(xiàn)的幾起案子葵诈,更是在濱河造成了極大的恐慌,老刑警劉巖祟同,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件作喘,死亡現(xiàn)場離奇詭異,居然都是意外死亡晕城,警方通過查閱死者的電腦和手機泞坦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來砖顷,“玉大人贰锁,你說我怎么就攤上這事÷蓑穑” “怎么了豌熄?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長几睛。 經(jīng)常有香客問我房轿,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任囱持,我火速辦了婚禮夯接,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纷妆。我一直安慰自己盔几,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布掩幢。 她就那樣靜靜地躺著逊拍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪际邻。 梳的紋絲不亂的頭發(fā)上芯丧,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天,我揣著相機與錄音世曾,去河邊找鬼缨恒。 笑死,一個胖子當(dāng)著我的面吹牛轮听,可吹牛的內(nèi)容都是我干的骗露。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼血巍,長吁一口氣:“原來是場噩夢啊……” “哼萧锉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起述寡,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤柿隙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辨赐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體优俘,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年掀序,在試婚紗的時候發(fā)現(xiàn)自己被綠了帆焕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡不恭,死狀恐怖叶雹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情换吧,我是刑警寧澤折晦,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站沾瓦,受9級特大地震影響满着,放射性物質(zhì)發(fā)生泄漏谦炒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一风喇、第九天 我趴在偏房一處隱蔽的房頂上張望宁改。 院中可真熱鬧,春花似錦魂莫、人聲如沸还蹲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谜喊。三九已至,卻和暖如春倦始,著一層夾襖步出監(jiān)牢的瞬間斗遏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工鞋邑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留最易,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓炫狱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親剔猿。 傳聞我的和親對象是個殘疾皇子视译,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容