
【相關推薦:javascript影片教學、web前端】
數組是一個特殊的對象,它和普通對象的差異不僅僅在於元素的順序存取、儲存。另一個重要的差異是:數組是可迭代的,也就是可以使用for ... of語句來存取(迭代)所有的元素。
我們可以簡單的做一個小實驗:
let arr = [1,2,3,4,5]for(let val of arr){
console.log(val)}程式碼執行結果:

以上程式碼就簡單的使用了數組的迭代特性,我們在存取數組元素的時候,不必使用元素的下標。
如果我們對一個普通物件使用for ... of語句會發生什麼事呢?
let obj = {
name:'xiaoming',
age:12,}for(let para of obj){ //程式碼會報錯console.log(para)}執行效果如下:

這證明普通的物件和陣列之間還有一個可迭代的差距,我們稱具備迭代功能的物件為可迭代物件。
如果我們希望一個物件可以迭代,必須為物件添加一個名為Symbol.iterator的方法(一個專門使物件可迭代的內建Symbol )。
方法作用包括:
for ... of迴圈迭代物件時,就會呼叫Symbol.iterator方法,而這個方法必須傳回一個迭代器(一個有next()方法的物件)。for ... of會不斷的呼叫迭代器的next()方法獲得下一個元素。next()方法傳回的內容必須符合格式: {done:Boolean,value:any} ,當done:true時,循環結束,否則value就是下一個值。迭代器:
迭代器是藉用
C++等語言的概念,迭代器的原理就像指標一樣,它指向資料集合中的某個元素,你可以取得它指向的元素,也可以移動它以取得其它元素。迭代器類似於陣列中下標的拓展,各種資料結構,如鍊錶(List)、集合(Set)、映射(Map)都有與之對應的迭代器。
JS中的迭代器是專門為了遍歷這項操作而設計的。每次取得到的迭代器總是初始指向第一個元素,且迭代器只有next()一種行為,直到取得到資料集的最後一個元素。我們無法靈活地移動迭代器的位置,所以,迭代器的任務,是按某種次序遍歷資料集中的元素。
實作一個可迭代物件:
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}//迭代結束}
}
}}for(let para of obj){
console.log(para)}程式碼執行效果:

注意,以上物件雖然可以進行迭代了,但是,迭代使用使用的材料並非對象,而是Symbol.iterator返回的迭代器(也是一個對象)。
以上程式碼建構了一個內建函數Symbol.iterator() ,這個函數回傳了一個迭代器物件。我們也可以採用另一個實作迭代器的方式:把物件本身做成迭代器:
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)}程式碼執行效果和上面的圖片展示相同。
這麼做雖然程式碼更加簡潔了,但是由於並沒有新的可迭代對象產生,我們就沒有辦法同時執行兩個
for ... of循環迭代同一個對象了,但是兩個並行的迭代在同一個對像上是非常罕見的。
我們可以總結可迭代對象的概念:
所謂可迭代對象,就是比普通對像多了一個名為Symbol.iterator方法的普通對象,這個方法回傳一個迭代器。
或者,具備Symbol.iterator同時具備next方法的物件也是一個可迭代的物件。
陣列和字串都是可以迭代的,我們可以很方便的使用for...of語句迭代數組中的字元元素:
let str = '123'for(let c of str){
console.log(c)}這對代理程式對( UTF-16擴充字元)同樣是有效的:
let str = '...'for(let c of str){
console.log(c)}執行效果如下:

並非只有for...of語句能夠使用迭代器,我們還可以明確的呼叫迭代器:
let str = '12345'let itr = str[Symbol.iterator]()while(true){
let result = itr.next()
if(result.done)break;
console.log(result.value)}程式碼執行效果:

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

把自訂的類別數組物件轉為數組:
let obj = {
0:'0',
1:'1',
2:'2',
length:3}let arr = Array.from(obj)console.log(arr)程式碼執行結果:

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

這裡透過映射函數,將本來應該產生字元數組轉為數字數組。
for...of語法的物件稱為可迭代物件Symbol.iterator方法的物件Symbol.iterator方法傳回了一個迭代器;next方法,該方法傳回下一個元素的值;next方法傳回值需要滿足格式{done:Boolean,value:nextVal} ,當done:true時,迭代結束Array.from可以把類別數組和可迭代物件轉為數組;
【相關推薦:javascript影片教學、web前端】
以上就是JavaScript類別陣列和可迭代物件的實作原理詳解的詳細內容,更多請關注原始碼網其它相關文章!