Array.from()方法就是將一個類數(shù)組對象或者可遍歷對象轉(zhuǎn)換成一個真正的數(shù)組。
將類數(shù)組對象轉(zhuǎn)換為真正數(shù)組:
letarrayLike = {
? 0:?'tom',?
????1:?'65',
????2:?'男',
????3: ['jane','john','Mary'],
????'length': 4
}
letarr = Array.from(arrayLike)
console.log(arr)?// ['tom','65','男',['jane','john','Mary']]
那么,如果將上面代碼中l(wèi)ength
屬性去掉呢?實踐證明,答案會是一個長度為0的空數(shù)組。
這里將代碼再改一下,就是具有l(wèi)ength屬性,但是對象的屬性名不再是數(shù)字類型的,而是其他字符串型的,代碼如下:
letarrayLike = {
????'name':?'tom',?
????'age':?'65',
????'sex':?'男',
????'friends': ['jane','john','Mary'],
????length: 4
}
letarr = Array.from(arrayLike)
console.log(arr)??// [ undefined, undefined, undefined, undefined ]
會發(fā)現(xiàn)結(jié)果是長度為4,元素均為undefined的數(shù)組
由此可見,要將一個類數(shù)組對象轉(zhuǎn)換為一個真正的數(shù)組,必須具備以下條件:
1、該類數(shù)組對象必須具有l(wèi)ength屬性,用于指定數(shù)組的長度。如果沒有l(wèi)ength屬性,那么轉(zhuǎn)換后的數(shù)組是一個空數(shù)組。
2、該類數(shù)組對象的屬性名必須為數(shù)值型或字符串型的數(shù)字
ps: 該類數(shù)組對象的屬性名可以加引號,也可以不加引號
實際應(yīng)用中,常見的類似數(shù)組的對象是DOM操作返回的NodeList集合,以及函數(shù)內(nèi)部的arguments對象。Array.from都可以將它們轉(zhuǎn)為真正的數(shù)組。
// NodeList對象letps =document.querySelectorAll('p');Array.from(ps).forEach(function(p){console.log(p);});// arguments對象functionfoo(){varargs =Array.from(arguments);// ...}
上面代碼中,querySelectorAll方法返回的是一個類似數(shù)組的對象,可以將這個對象轉(zhuǎn)為真正的數(shù)組,再使用forEach方法。
只要是部署了Iterator接口的數(shù)據(jù)結(jié)構(gòu),Array.from都能將其轉(zhuǎn)為數(shù)組。
Array.from('hello')// ['h', 'e', 'l', 'l', 'o']letnamesSet =newSet(['a','b'])Array.from(namesSet)// ['a', 'b']
上面代碼中,字符串和Set結(jié)構(gòu)都具有Iterator接口,因此可以被Array.from轉(zhuǎn)為真正的數(shù)組。
如果參數(shù)是一個真正的數(shù)組,Array.from會返回一個一模一樣的新數(shù)組。
Array.from([1,2,3])// [1, 2, 3]
值得提醒的是,擴展運算符(...)也可以將某些數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為數(shù)組。
// arguments對象functionfoo(){varargs = [...arguments];}// NodeList對象[...document.querySelectorAll('div')]
擴展運算符背后調(diào)用的是遍歷器接口(Symbol.iterator),如果一個對象沒有部署這個接口,就無法轉(zhuǎn)換。Array.from方法則是還支持類似數(shù)組的對象。所謂類似數(shù)組的對象,本質(zhì)特征只有一點,即必須有l(wèi)ength屬性。因此,任何有l(wèi)ength屬性的對象,都可以通過Array.from方法轉(zhuǎn)為數(shù)組,而此時擴展運算符就無法轉(zhuǎn)換。
Array.from({length:3});// [ undefined, undefined, undefined ]
上面代碼中,Array.from返回了一個具有三個成員的數(shù)組,每個位置的值都是undefined。擴展運算符轉(zhuǎn)換不了這個對象。
對于還沒有部署該方法的瀏覽器,可以用Array.prototype.slice方法替代。
consttoArray =(() =>Array.from ?Array.from :obj=>[].slice.call(obj))();
Array.from還可以接受第二個參數(shù),作用類似于數(shù)組的map方法,用來對每個元素進行處理,將處理后的值放入返回的數(shù)組。
Array.from(arrayLike, x => x * x);// 等同于Array.from(arrayLike).map(x=>x * x);Array.from([1,2,3], (x) => x * x)// [1, 4, 9]
下面的例子是取出一組DOM節(jié)點的文本內(nèi)容。
letspans =document.querySelectorAll('span.name');// map()letnames1 =Array.prototype.map.call(spans, s => s.textContent);// Array.from()letnames2 =Array.from(spans, s => s.textContent)
下面的例子將數(shù)組中布爾值為false的成員轉(zhuǎn)為0。
Array.from([1, ,2, ,3],(n) => n ||0)// [1, 0, 2, 0, 3]
另一個例子是返回各種數(shù)據(jù)的類型。
functiontypesOf(){returnArray.from(arguments, value =>typeofvalue)}typesOf(null, [],NaN)// ['object', 'object', 'number']
如果map函數(shù)里面用到了this關(guān)鍵字,還可以傳入Array.from的第三個參數(shù),用來綁定this。
Array.from()可以將各種值轉(zhuǎn)為真正的數(shù)組,并且還提供map功能。這實際上意味著,只要有一個原始的數(shù)據(jù)結(jié)構(gòu),你就可以先對它的值進行處理,然后轉(zhuǎn)成規(guī)范的數(shù)組結(jié)構(gòu),進而就可以使用數(shù)量眾多的數(shù)組方法。
Array.from({length:2},() =>'jack')// ['jack', 'jack']
上面代碼中,Array.from的第一個參數(shù)指定了第二個參數(shù)運行的次數(shù)。這種特性可以讓該方法的用法變得非常靈活。
Array.from()的另一個應(yīng)用是,將字符串轉(zhuǎn)為數(shù)組,然后返回字符串的長度。因為它能正確處理各種Unicode字符,可以避免JavaScript將大于\uFFFF的Unicode字符,算作兩個字符的bug。
functioncountSymbols(string){returnArray.from(string).length;
}