2018-03-26

擁抱 ES6 之?dāng)?shù)組擴(kuò)展

https://segmentfault.com/a/1190000003857670?_ea=396445

新增的數(shù)組方法

from

from?方法用于將兩類對象轉(zhuǎn)為真正的數(shù)組:類似數(shù)組的對象(array-like object)和可遍歷(iterable)的對象(包括ES6新增的數(shù)據(jù)結(jié)構(gòu)Set和Map)。

常用方式

將字符串轉(zhuǎn)化為數(shù)組。

Array.from('hello') // [?'h',?'e',?'l',?'l',?'o'?]

傳參為數(shù)組類型對象時原樣輸出。

Array.from([1,?2,?3])?// [ 1, 2, 3 ]

將 Set 對象轉(zhuǎn)換為數(shù)組。

Array.from(new?Set(['a',?'b']))?// [ 'a', 'b' ]

傳參為無 length 屬性的 Object。

Array.from({?0:?'a',?1:?'b',?2:?'c'?})?// []

傳參為有 length 屬性的 Object。

Array.from({?0:?'a',?1:?'b',?2:?'c', length:?3?}) // [?'a',?'b',?'c'?]

通過對比可以得知一個結(jié)論:

任何?length?屬性的對象,都可以通過?from?方法轉(zhuǎn)為數(shù)組。

與此同時,Spread 運算符?...?也可以將實現(xiàn)了遍歷器接口?Symbol.iterator?的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為數(shù)組。

var o = {0:'a',1:'b',2:'c', length:3}Array.from(o)//['a','b','c'][...o]//TypeError

通過上述??可以說明?...?的局限性。對象賦值了?length?屬性,但并未實現(xiàn)?Symbol.iterator?,所以報錯。

再舉個比較實用的場景,羅列一下類數(shù)組對象?arguments?轉(zhuǎn)換為數(shù)組的幾種方式。(類數(shù)組對象實現(xiàn)了遍歷器接口Symbol.iterator,它有l(wèi)ength屬性,數(shù)據(jù)結(jié)構(gòu)和數(shù)組很像,但是它不是數(shù)組。具體的可以參考文章《Array-like Objects in JavaScript》)。

ES5

functionfoo(){? ? [].slice.call(arguments);}

ES6?Array.from

functionfoo(){Array.from(arguments);// [ 'a', 'b', 'c' ]}

ES6 Spread Operator?...

functionfoo(){? ? [...arguments]; // ['a','b','c']}

將對象轉(zhuǎn)換為數(shù)組的幾種形式。

// key值為整形varo = {0:'a',1:'b',2:'c',length:3}Array.from(o)// [ 'a', 'b', 'c' ]// key值為只包含數(shù)字內(nèi)容的字符串varo = {'0':'a','1':'b','2':'c',length:3}console.log(Array.from(o));// [ 'a', 'b', 'c' ]// key值不從0起varo = {1:'a',2:'b',3:'c',length:3}Array.from(o)// [ undefined, 'a', 'b' ]// key值為不能轉(zhuǎn)化為數(shù)字的字符串varo = {a:'a',b:'b',c:'c',length:3}Array.from(o)// [ undefined, undefined, undefined ]// key值為包含數(shù)字和字符混雜的形式varo = {'0a':'a','1':'b','2':'c',length:3}console.log(Array.from(o));// [ undefined, 'b', 'c' ]// key值既有字符又有數(shù)字varo = {a:'a',2:'b',c:'c',length:3}console.log(Array.from(o));// [ undefined, undefined, 'b' ]// key值既有字符又有數(shù)字并且length屬性大于對象除length屬性外定義屬性的個數(shù)varo = {a:'a',2:'b',c:'c',length:4}Array.from(o)// [ undefined, undefined, 'b', undefined ]

from?是通過key作為下標(biāo)并且參照?length?屬性大小來填充元素的。當(dāng)沒有合適的元素插入時就會插入?undefined?補(bǔ)位。

兼容性

對于還沒有部署該方法的瀏覽器,可以使用Array.prototype.slice方法替代。

const?toArray =?(() =>?Array.from???Array.from?: obj =>?Array.prototype.slice.call(obj))();

寫的很精簡有木有,但是可能會讓人覺得一下子不太好消化。

consttoArray = (function(){returnArray.from ?Array.from :function(obj){returnArray.prototype.slice.call(obj);? ? };})();

這段代碼和上段代碼有異曲同工之妙,會不會好理解一些呢?如果覺得還是不太好理解,沒事兒,咱再看一段代碼。

consttoArray = (function(){if(Array.from) {returnArray.from;? ? }else{returnfunction(obj){returnArray.prototype.slice.call(obj);? ? ? ? }? ? }})();

看到這個簡單明了了吧,如果還是有什么疑問的話,那只能說,媽媽叫你回家學(xué)基礎(chǔ)了。

類似map()的用法

Array.from(arrayLike,x=>x * x);// 等同于Array.from(arrayLike).map(x=>x * x);Array.from([1,2,3],(x) =>x * x)// [ 1, 4, 9 ]

下面的例子將數(shù)組中布爾值為false的成員轉(zhuǎn)為0。

Array.from([1, ,?2, ,?3], (n) => n ||?0)?// [1, 0, 2, 0, 3]

Array.from()可以將各種值轉(zhuǎn)為真正的數(shù)組,并且還提供map功能。這實際上意味著,你可以在數(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;}

Array.of()

Array.of與Array()的異同

Array.of的行為很統(tǒng)一。

Array.of()// []Array.of(3)// [ 3 ]Array.of(3,11,8)// [ 3, 11, 8 ]Array.of(undefined)// [undefined]

當(dāng)傳入單個參數(shù)時,Array()的行為表現(xiàn)的不統(tǒng)一。

Array()// []Array(3)// [ , ,? ]Array(3,11,8)// [ 3, 11, 8 ]

童鞋們知道當(dāng)傳入單個參數(shù)時,Array是怎么處理的么?生成的數(shù)組的元素都是什么類型的呢?既然之前學(xué)了Array.from類似map()方法的運用,這里怎么的也得實戰(zhàn)一下子啊。

functiontypesof() {returnArray.from(arguments,v => typeof v);}typesof(...Array(3)) // ['undefined','undefined','undefined' ]

這里還順帶了操作擴(kuò)展符(...)逆轉(zhuǎn)化數(shù)組的芝士點。不懂的童鞋看看阮一峰老濕的《函數(shù)的擴(kuò)展》吧。請叫我雷鋒。

兼容性

Array.of方法可以用下面的代碼模擬實現(xiàn)。

functionArrayOf() {return[].slice.call(arguments);}

數(shù)組實例的copyWithin()

常用方式

數(shù)組實例的copyWithin方法,在當(dāng)前數(shù)組內(nèi)部,將指定位置的成員復(fù)制到其他位置(會覆蓋原有成員),然后返回當(dāng)前數(shù)組。也就是說,使用這個方法,會修改當(dāng)前數(shù)組。

Array.prototype.copyWithin(target, start = 0, end = this.length)

它接受三個參數(shù)。

target(必需):從該位置開始替換數(shù)據(jù)。

start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為0。如果為負(fù)值,表示倒數(shù)。

end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長度。如果為負(fù)值,表示倒數(shù)。

這三個參數(shù)都應(yīng)該是數(shù)值,如果不是,會自動轉(zhuǎn)為數(shù)值。

[1,?2,?3,?4,?5].copyWithin(0,?3)?// [ 4, 5, 3, 4, 5 ]

上面代碼表示將從3號位直到數(shù)組結(jié)束的成員(4和5),復(fù)制到從0號位開始的位置,結(jié)果覆蓋了原來的1和2。

下面是更多例子。

// 將3號位復(fù)制到0號位[1,2,3,4,5].copyWithin(0,3,4)// [ 4, 2, 3, 4, 5 ]// 上面和下面這兩個方法等同// -2相當(dāng)于3號位,-1相當(dāng)于4號位[1,2,3,4,5].copyWithin(0,-2,-1)// [ 4, 2, 3, 4, 5 ]// 將3號位復(fù)制到0號位[].copyWithin.call({length:5,3:1},0,3)// { '0': 1, '3': 1, length: 5 }// 將2號位到數(shù)組結(jié)束,復(fù)制到0號位vari32a =newInt32Array([1,2,3,4,5]);i32a.copyWithin(0,2);// Int32Array [3, 4, 5, 4, 5]

兼容性

對于沒有部署TypedArray的copyWithin方法的平臺,需要采用下面的寫法。

[].copyWithin.call(new Int32Array([1,2,3,4,5]),0,3,4);// Int32Array [4, 2, 3, 4, 5]

多說幾句

既然使用了copuWithin方法會修改當(dāng)前數(shù)組,那么我們就總結(jié)一下還有哪些方法也會更改當(dāng)前數(shù)組,哪些則不會。只列取常用的,貴精不貴全。

不會修改當(dāng)前數(shù)組的方法

concat()方法用于連接兩個或多個數(shù)組。該方法不會改變現(xiàn)有的數(shù)組,而僅僅會返回被連接數(shù)組的一個副本。

vararr =Array.of(1,2,3);varresArr = arr.concat(4);arr// [ 1, 2, 3 ]resArr// [ 1, 2, 3, 4 ]

join()方法用于把數(shù)組中的所有元素放入一個字符串。元素是通過指定的分隔符進(jìn)行分隔的。

vararr =Array.of(1,2,3);varresStr = arr.join(",");arr// [ 1, 2, 3 ]resStr// 1,2,3

會修改當(dāng)前數(shù)組的方法

pop()方法用于刪除并返回數(shù)組的最后一個元素。

vararr =Array.of(1,2,3);varresEle = arr.pop();arr// [ 1, 2 ]resEle// 3

push()方法可向數(shù)組的末尾添加一個或多個元素,并返回新的長度。

vararr =Array.of(1,2,3);varresLen = arr.push('a');arr// [ 1, 2, 3, 'a' ]resLen// 4

sort()方法用于對數(shù)組的元素進(jìn)行排序。

vararr =Array.of(3,11,8);varres = arr.sort();arr// [ 11, 3, 8 ]res// [ 11, 3, 8 ]

結(jié)果是不是很意外,沒錯,排序并不是按整型大小,而是字符串對比,就是取第一個字符的ANSI碼對比,小的排前面,相同的話取第二個字符再比,如果要按整型數(shù)值比較,可以這樣。

vararr =Array.of(3,11,8);varres = arr.sort((a, b) =>a - b);arr// [ 3, 8, 11 ]res// [ 3, 8, 11 ]

reverse()方法用于顛倒數(shù)組中元素的順序。

vararr =Array.of(3,11,8,9);varres = arr.reverse();arr// [ 9, 8, 11, 3 ]res// [ 9, 8, 11, 3 ]

數(shù)組實例的find()和findIndex()

數(shù)組實例的find方法,用于找出第一個符合條件的數(shù)組成員。

它的參數(shù)是一個回調(diào)函數(shù),所有數(shù)組成員依次執(zhí)行該回調(diào)函數(shù),直到找出第一個返回值為true的成員,然后返回該成員。如果沒有符合條件的成員,則返回undefined。

[1,?4,?-5,?10].find((n) => n <?0)?// -5

上面代碼找出數(shù)組中第一個小于0的成員。

[1,5,10,15].find(function(value, index, arr) {? ? return value >9;})// 10

上面代碼中,find方法的回調(diào)函數(shù)可以接受三個參數(shù),依次為當(dāng)前的值、當(dāng)前的位置和原數(shù)組。

數(shù)組實例的findIndex方法的用法與find方法非常類似,返回第一個符合條件的數(shù)組成員的位置,如果所有成員都不符合條件,則返回-1。

數(shù)組實例的fill()

fill方法使用給定值,填充一個數(shù)組。

['a','b','c'].fill(7)// [7, 7, 7]newArray(3).fill(7)// [7, 7, 7]

上面代碼表明,fill方法用于空數(shù)組的初始化非常方便。數(shù)組中已有的元素,會被全部抹去。

fill方法還可以接受第二個和第三個參數(shù),用于指定填充的起始位置和結(jié)束位置。

['a',?'b',?'c'].fill(7,?1,?2) // ['a',?7,?'c']

凡是帶這種傳參有startIndex和endIndex的方法,都是以startIndex開始,以endIndex為結(jié)束但不包含endIndex元素上的值。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 數(shù)組是一種可變的、可索引的數(shù)據(jù)集合。在Scala中用Array[T]的形式來表示Java中的數(shù)組形式 T[]。 v...
    時待吾閱讀 1,067評論 0 0
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,569評論 0 13
  • Javascript有很多數(shù)組的方法,有的人有W3C的API,還可以去MDN上去找,但是我覺得API上說的不全,M...
    頑皮的雪狐七七閱讀 4,499評論 0 6
  • Properties 一個public或private的Objective-C屬性使用@property語法聲明的...
    Runxing閱讀 417評論 0 2
  • 22天對于人的一輩子來說不算什么,但是在這個夏天,我通過貓叔行動營的學(xué)習(xí),在工作,學(xué)習(xí)和生活上帶了了很大的改變。 ...
    四海遨游閱讀 627評論 0 2

友情鏈接更多精彩內(nèi)容