JavaScript詳解類數(shù)組與可迭代對象的實現(xiàn)原理
可迭代對象(Iterable object)
數(shù)組是一個特殊的對象,它和普通對象的區(qū)別不僅僅在于元素的順序訪問、存儲。另外一個重要的區(qū)別是:數(shù)組是可迭代的,也就是可以使用for ... of語句訪問(迭代)所有的元素。
我們可以簡單的做一個小實驗:
let arr = [1,2,3,4,5]
for(let val of arr){
console.log(val)
}
代碼執(zhí)行結(jié)果:

以上代碼就簡單的使用了數(shù)組的迭代特性,我們在訪問數(shù)組元素的時候,不必使用元素的下標。
如果我們對一個普通對象使用for ... of語句會發(fā)生什么呢?
let obj = {
name:'xiaoming',
age:12,
}
for(let para of obj){ //代碼會報錯
console.log(para)
}
執(zhí)行效果如下:

這就證明普通的對象和數(shù)組之間還有一個可迭代的差距,我們稱具備迭代功能的對象為可迭代對象。
Symbol.iterator
如果我們希望一個對象可以迭代,必須為對象添加一個名為Symbol.iterator的方法(一個專門使對象可迭代的內(nèi)建Symbol)。
方法作用包括:
- 當使用
for ... of循環(huán)迭代對象時,就會調(diào)用Symbol.iterator方法,這個方法必須返回一個迭代器(一個有next()方法的對象)。 - 得到迭代器后,
for ... of會不斷的調(diào)用迭代器的next()方法獲得下一個元素 next()方法返回的內(nèi)容必須符合格式:{done:Boolean,value:any},當done:true時,循環(huán)結(jié)束,否則value就是下一個值。
迭代器:
迭代器是借鑒C++等語言的概念,迭代器的原理就像指針一樣,它指向數(shù)據(jù)集合中的某個元素,你可以獲取它指向的元素,也可以移動它以獲取其它元素。迭代器類似于數(shù)組中下標的拓展,各種數(shù)據(jù)結(jié)構(gòu),如鏈表(List)、集合(Set)、映射(Map)都有與之對應(yīng)的迭代器。
JS中的迭代器是專門為了遍歷這一操作設(shè)計的。每次獲取到的迭代器總是初始指向第一個元素,并且迭代器只有next()一種行為,直到獲取到數(shù)據(jù)集的最后一個元素。我們無法靈活移動迭代器的位置,所以,迭代器的任務(wù),是按某種次序遍歷數(shù)據(jù)集中的元素。
實現(xiàn)一個可迭代對象:
let obj = {
from:1,
to:5,
}
obj[Symbol.iterator] = function(){
//返回一個迭代器
return {
current:this.from,
last:this.to,
next(){
if(this.current<this.last){
return {done:false,value:this.current++}
}else{
return {done:true}//迭代結(jié)束
}
}
}
}
for(let para of obj){
console.log(para)
}代碼執(zhí)行效果:

注意,以上對象雖然可以進行迭代了,但是,迭代使用使用的材料并非對象,而是Symbol.iterator返回的迭代器(也是一個對象)。
把對象本身構(gòu)造成迭代器
以上代碼構(gòu)造了一個內(nèi)建函數(shù)Symbol.iterator(),這個函數(shù)返回了一個迭代器對象。我們還可以采用另外一種實現(xiàn)迭代器的方式:把對象本身做成迭代器:
let obj = {
from:1,
to:5,
[Symbol.iterator](){
this.current = this.from;
return this;//返回對象本身
},
next(){//給對象添加一個next方法
if(this.current<this.to){
return {done:false,value:this.current++}
}else{
return {done:true}
}
}
}
for(let para of obj){
console.log(para)
}
代碼執(zhí)行效果和上面的圖片展示相同。
這么做雖然代碼更加簡潔了,但是由于并沒有新的可迭代對象產(chǎn)生,我們就沒有辦法同時執(zhí)行兩個for ... of循環(huán)迭代同一個對象了,但是兩個并行的迭代在同一個對象上是非常罕見的。
我們可以總結(jié)可迭代對象的概念:
所謂可迭代對象,就是比普通對象多了一個名為Symbol.iterator方法的普通對象,這個方法返回一個迭代器。
或者,一個具備Symbol.iterator同時具備next方法的對象也是一個可迭代的對象。
String也是可迭代的
數(shù)組和字符串都是可以迭代的,我們可以很方便的使用for...of語句迭代數(shù)組中的字符元素:
let str = '123'
for(let c of str){
console.log(c)
}
這對于代理對(UTF-16擴展字符)同樣是有效的:
let str = '?????????????????????'
for(let c of str){
console.log(c)
}
執(zhí)行效果如下:

String的迭代器
并非只有for...of語句能夠使用迭代器,我們還可以顯式的調(diào)用迭代器:
let str = '12345'
let itr = str[Symbol.iterator]()
while(true){
let result = itr.next()
if(result.done)break;
console.log(result.value)
}
代碼執(zhí)行效果:

以上代碼執(zhí)行了遍歷字符串字符的操作,是不是覺得可迭代對象就沒有這么神秘了!
類數(shù)組對象和可迭代對象
類數(shù)組和可迭代在遍歷功能上非常相似,都可以方便的方式內(nèi)部元素,但是二者仍然有明顯的區(qū)別:
iterable可迭代對象:實現(xiàn)了Symbol.iterator的對象;array-like類數(shù)組對象:具有數(shù)字索引,并且有length屬性;
字符串就是一個即使類數(shù)組又是可迭代的對象。
可迭代和類數(shù)組對象通常都不是數(shù)組,如果我們想把一個可迭代或者類數(shù)組對象轉(zhuǎn)為數(shù)組,需要使用Array.from方法。
Array.from
使用Array.from將字符串轉(zhuǎn)為數(shù)組:
let str = '123' let arr = Array.from(str) console.log(arr)
代碼執(zhí)行效果如下:

把自定義的類數(shù)組對象轉(zhuǎn)為數(shù)組:
let obj = {
0:'0',
1:'1',
2:'2',
length:3
}
let arr = Array.from(obj)
console.log(arr)
代碼執(zhí)行結(jié)果:

Array.from的完整語法:
Array.from(obj[, mapFunc, thisArg])
mapFunc方法會在生成數(shù)組之前對每個可迭代或類數(shù)組元素調(diào)用,如果mapFunc是一個成員方法,可以使用thisArg提供this指針。
舉個例子:
let str = '12345' let arr = Array.from(str,itm=>+itm) console.log(arr)
代碼執(zhí)行結(jié)果:

這里通過映射函數(shù),將本應(yīng)該生成字符數(shù)組轉(zhuǎn)為數(shù)字數(shù)組。
總結(jié)
- 可以使用
for...of語法的對象被稱為可迭代對象 - 可迭代對象是在普通對象的基礎(chǔ)上實現(xiàn)了
Symbol.iterator方法的對象 Symbol.iterator方法返回了一個迭代器;- 迭代器包含一個
next方法,該方法返回下一個元素的值; next方法返回值需要滿足格式{done:Boolean,value:nextVal},當done:true時,迭代結(jié)束Array.from可以把類數(shù)組和可迭代對象轉(zhuǎn)為數(shù)組;
到此這篇關(guān)于JavaScript詳解類數(shù)組與可迭代對象的實現(xiàn)原理的文章就介紹到這了,更多相關(guān)JavaScript 類數(shù)組與可迭代對象內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺析C/C++,Java,PHP,JavaScript,Json數(shù)組、對象賦值時最后一個元素后面是否可以帶逗號
這篇文章主要介紹了淺析C/C++,Java,PHP,JavaScript,Json數(shù)組、對象賦值時最后一個元素后面是否可以帶逗號的相關(guān)資料,需要的朋友可以參考下2016-03-03
微信小程序?qū)崿F(xiàn)image組件圖片自適應(yīng)寬度比例顯示的方法
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)image組件圖片自適應(yīng)寬度比例顯示的方法,簡單講述了image組件的常用屬性,并結(jié)合實例形式分析了微信小程序?qū)崿F(xiàn)圖片自適應(yīng)寬度比例的相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
JavaScript實現(xiàn)選中文字提示新浪微博分享效果
這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)選中文字提示新浪微博分享效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06
最好用的Bootstrap fileinput.js文件上傳組件
這篇文章主要為大家詳細介紹了最好用的Bootstrap fileinput.js文件上傳組件的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-12-12

