ES6(十):數(shù)組擴展

前面的話


??數(shù)組是一種基礎的JS對象,隨著時間推進,JS中的其他部分一直在演進,而直到ES5標準才為數(shù)組對象引入一些新方法來簡化使用瑰步。ES6標準繼續(xù)改進數(shù)組钞速,添加了很多新功能鱼炒。本文將詳細介紹ES6數(shù)組擴展

靜態(tài)方法

??在ES6以前,創(chuàng)建數(shù)組的方式主要有兩種娇未,一種是調(diào)用Array構造函數(shù)责静,另一種是用數(shù)組字面量語法袁滥,這兩種方法均需列舉數(shù)組中的元素,功能非常受限灾螃。如果想將一個類數(shù)組對象(具有數(shù)值型索引和length屬性的對象)轉(zhuǎn)換為數(shù)組题翻,可選的方法也十分有限,經(jīng)常需要編寫額外的代碼腰鬼。為了進一步簡化JS數(shù)組的創(chuàng)建過程嵌赠,ES6新增了Array.of()Array.from()兩個方法

【Array.of()】

ES6之所以向JS添加新的創(chuàng)建方法塑荒,是要幫助開發(fā)者們規(guī)避通過Array構造函數(shù)創(chuàng)建數(shù)組時的怪異行為

let items =new Array(2);
console.log(items.length); // 2
console.log(items[0]);// undefined
console.log(items[1]);// undefined
items =newArray("2");
console.log(items.length); // 1
console.log(items[0]);// "2"
items =new Array(1, 2);
console.log(items.length); // 2
console.log(items[0]);// 1
console.log(items[1]);// 2
items =new Array(3, "2");
console.log(items.length); // 2
console.log(items[0]);// 3
console.log(items[1]);// "2"
  • 如果給Array構造函數(shù)傳入一個數(shù)值型的值,那么數(shù)組的length屬性會被設為該值姜挺。如果傳入多個值齿税,此時無論這些值是不是數(shù)值型的,都會變?yōu)閿?shù)組的元素初家。這個特性令人感到困惑偎窘,不可能總是注意傳入數(shù)據(jù)的類型,所以存在一定的風險

  • ES6通過引入Array.of()方法來解決這個問題溜在。Array.of()與Array構造函數(shù)的工作機制類似,只是不存在單一數(shù)值型參數(shù)值的特例他托,無論有多少參數(shù)掖肋,無論參數(shù)是什么類型的,Array.of()方法總會創(chuàng)建一個包含所有參數(shù)的數(shù)組

let items = Array.of(1, 2);
console.log(items.length); // 2
console.log(items[0]);// 1
console.log(items[1]);// 2
items = Array.of(2);
console.log(items.length); // 1
console.log(items[0]);// 2
items = Array.of("2");
console.log(items.length); // 1
console.log(items[0]);// "2"
  • 要用Array.of()方法創(chuàng)建數(shù)組赏参,只需傳入希望在數(shù)組中包含的值志笼。第一個示例創(chuàng)建了一個包含兩個數(shù)字的數(shù)組;第二個數(shù)組包含一個數(shù)宇把篓;最后一個數(shù)組包含一個字符串纫溃。這與數(shù)組字面量的使用方法很相似,在大多數(shù)時候韧掩,可以用數(shù)組字面量來創(chuàng)建原生數(shù)組紊浩,但如果需要給一個函數(shù)傳入Array的構造函數(shù),則可能更希望傳入Array.of()來確保行為一致
function createArray(arrayCreator, value) {  
  return arrayCreator(value);
}
let items = createArray(Array.of, value);
  • 在這段代碼中心createArray()函數(shù)接受兩個參數(shù)疗锐,一個是數(shù)組創(chuàng)造者函數(shù)坊谁,另一個是要插入數(shù)組的值』可以傳入Array.of()作為createArray()方法的第一個參數(shù)來創(chuàng)建新數(shù)組口芍,如果不能保證傳入的值一定不是數(shù)字,那么直接傳入Array會非常危險

[注意] Array.of()方法不通過Symbol.species屬性確定返回值的類型雇卷,它使用當前構造函數(shù)(也就是of()方法中的this值)來確定正確的返回數(shù)據(jù)的類型

【Array.from()】

?? JS不支持直接將非數(shù)組對象轉(zhuǎn)換為真實數(shù)組鬓椭,arguments就是一種類數(shù)組對象,如果要把它當作數(shù)組使用則必須先轉(zhuǎn)換該對象的類型关划。在ES5中小染,可能需要編寫如下函數(shù)來把類數(shù)組對象轉(zhuǎn)換為數(shù)組

function makeArray(arrayLike) { 
  var result = [];   
  for(vari = 0, len = arrayLike.length; i < len; i++) {
    result.push(arrayLike[i]);
  }   
  return result;
}
function doSomething() {   
  var args = makeArray(arguments);    // 使用 args
}
  • 這種方法先是手動創(chuàng)建一個result數(shù)組,再將arguments對象里的每一個元素復制到新數(shù)組中祭玉。盡管這種方法有效氧映,但需要編寫很多代碼才能完成如此簡單的操作。最終脱货,開發(fā)者們發(fā)現(xiàn)了一種只需編寫極少代碼的新方法岛都,調(diào)用數(shù)組原生的slice()方法可以將非數(shù)組對象轉(zhuǎn)換為數(shù)組
function makeArray(arrayLike) { 
  return Array.prototype.slice.call(arrayLike);
}
function doSomething() { 
  var args = makeArray(arguments);    // 使用 args
}
  • 這段代碼的功能等價于之前的示例律姨,將slice()方法執(zhí)行時的this值設置為類數(shù)組對象,而slice()對象只需數(shù)值型索引和length屬性就能夠正確運行臼疫,所以任何類數(shù)組對象都能被轉(zhuǎn)換為數(shù)組

  • 盡管這項技術不需要編寫很多代碼择份,但是我們調(diào)用Array.prototype.slice.call(arrayLike)時不能直覺地想到這是在將arrayLike轉(zhuǎn)換成一個數(shù)組。所幸烫堤,ES6添加了一個語義清晰荣赶、語法簡潔的新方法Array.from()來將對象轉(zhuǎn)化為數(shù)組

  • Array.from()方法可以接受可迭代對象或類數(shù)組對象作為第一個參數(shù),最終返回一個數(shù)組

function doSomething() {   
  var args = Array.from(arguments);    // 使用 args 
}
  • Array.from()方法調(diào)用會基于arguments對象中的元素創(chuàng)建一個新數(shù)組鸽斟,argsArray的一個實例拔创,包含arguments對象中同位置的相同值

[注意] Array.from()方法也是通過this來確定返回數(shù)組的類型的

映射轉(zhuǎn)換

??如果想要進一步轉(zhuǎn)化數(shù)組,可以提供一個映射函數(shù)作為Array.from()的第二個參數(shù)富蓄,這個函數(shù)用來將類數(shù)組對象中的每一個值轉(zhuǎn)換成其他形式剩燥,最后將這些結果儲存在結果數(shù)組的相應索引中

function translate() {  
  return Array.from(arguments, (value) => value + 1);
}
let numbers = translate(1, 2, 3);
console.log(numbers); // 2,3,4
  • 在這段代碼中,為Array.from()方法傳入映射函數(shù)(value)=>value+1立倍,數(shù)組中的每個元素在儲存前都會被加1灭红。如果用映射函數(shù)處理對象,也可以給Array.from()方法傳入第三個參數(shù)來表示映射函數(shù)的this
let helper ={
  diff: 1,
  add(value) {    
    return value +this.diff;
}
};
function translate() {    
  return Array.from(arguments, helper.add, helper);
}
let numbers = translate(1, 2, 3);
console.log(numbers); // 2,3,4
  • 此示例傳入helper.add()作為轉(zhuǎn)換用的映射函數(shù)口注,由于該方法使用了this.diff屬性变擒,因此需要為Array.from()方法提供第三個參數(shù)來指定this的值,從而無須通過調(diào)用bind()方法或其他方式來指定this的值了用Array.from()轉(zhuǎn)換可迭代對象

  • Array.from()方法可以處理類數(shù)組對象和可迭代對象寝志,也就是說該方法能夠?qū)⑺泻?code>Symbol.iterator屬性的對象轉(zhuǎn)換為數(shù)組

let numbers = {   
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};
let numbers2 = Array.from(numbers, (value) => value + 1);
console.log(numbers2); // 2,3,4
  • 由于numbers是一個可迭代對象娇斑,因此可以直接將它傳入Array.from()來轉(zhuǎn)換成數(shù)組。此處的映射函數(shù)將每一個數(shù)字加1澈段,所以結果數(shù)組最終包含的值為2悠菜、3和4

[注意]如果一個對象既是類數(shù)組又是可迭代的,那么Array.from()方法會根據(jù)迭代器來決定轉(zhuǎn)換哪個值

實例方法

ES6延續(xù)了ES5的一貫風格败富,也為數(shù)組添加了幾個新的方法:includes()方法返回一個布爾值悔醋,表示數(shù)組是否包含給定的值;find()方法和findIndex()方法可以協(xié)助開發(fā)者在數(shù)組中查找任意值兽叮;fill()方法和copyWithin()方法的靈感則來自于定型數(shù)組的使用過程芬骄,定型數(shù)組也是ES6中的新特性,是一種只包含數(shù)字的數(shù)組

【includes()】

  • Array.prototype.includes方法返回一個布爾值鹦聪,表示某個數(shù)組是否包含給定的值账阻,與字符串的includes方法類似。ES2016引入了該方法
[1, 2, 3].includes(2)// true
[1, 2, 3].includes(4)// false
[1, 2, NaN].includes(NaN)// true
  • 該方法的第二個參數(shù)表示搜索的起始位置泽本,默認為0淘太。如果第二個參數(shù)為負數(shù),則表示倒數(shù)的位置,如果這時它大于數(shù)組長度(比如第二個參數(shù)為-4蒲牧,但數(shù)組長度為3)撇贺,則會重置為從0開始
[1, 2, 3].includes(3, 3);// false
[1, 2, 3].includes(3, -1);// true
  • 沒有該方法之前,我們通常使用數(shù)組的indexOf方法冰抢,檢查是否包含某個值
if(arr.indexOf(el) !== -1) { 
 // ...
}
  • indexOf方法有兩個缺點松嘶,一是不夠語義化,它的含義是找到參數(shù)值的第一個出現(xiàn)位置挎扰,所以要去比較是否不等于-1翠订,表達起來不夠直觀。二是遵倦,它內(nèi)部使用嚴格相等運算符(===)進行判斷尽超,這會導致對NaN的誤判
[NaN].indexOf(NaN)// -1
  • includes使用的是不一樣的判斷算法,就沒有這個問題
[NaN].includes(NaN)// true
  • 下面代碼用來檢查當前環(huán)境是否支持該方法骇吭,如果不支持橙弱,部署一個簡易的替代版本
const contains = (() =>
Array.prototype.includes ? (arr, value) =>
   arr.includes(value) : (arr, value) =>
   arr.some(el => el ===value)
)();
contains(['foo', 'bar'], 'baz');// => false
  • 另外,MapSet 數(shù)據(jù)結構有一個has方法燥狰,需要注意與includes區(qū)分

1、Map結構的has方法斜筐,是用來查找鍵名的龙致,比如Map.prototype.has(key)WeakMap.prototype.has(key)顷链、Reflect.has(target,propertyKey)

2目代、Set結構的has方法,是用來查找值的嗤练,比如Set.prototype.has(value)榛了、WeakSet.prototype.has(value)

【find()和findIndex()】

??由于沒有內(nèi)建的數(shù)組搜索方法,因此ES5正式添加了indexOf()lastIndexOf()兩個方法煞抬,可以用它們在數(shù)組中查找特定的值霜大。雖然這是一個巨大的進步,但這兩種方法仍有局限之處革答,即每次只能查找一個值战坤,如果想在系列數(shù)字中查找第一個偶數(shù),則必須自己編寫代碼來實現(xiàn)残拐。于是ES6引入了find()方法和findIndex()方法來解決這個問題

  • find()方法和findIndex()方法都接受兩個參數(shù):一個是回調(diào)函數(shù)途茫;另一個是可選參數(shù),用于指定回調(diào)函數(shù)中this的值溪食。執(zhí)行回調(diào)函數(shù)時囊卜,傳入的參數(shù)分別為數(shù)組中的某個元素、該元素在數(shù)組中的索引和數(shù)組本身,與傳入map()forEach()方法的參數(shù)相同栅组。如果給定的值滿足定義的標準雀瓢,回調(diào)函數(shù)應返回true。一旦回調(diào)函數(shù)返回true笑窜,find()方法和findIndex()方法都會立即停止搜索數(shù)組剩余的部分

  • 二者間唯一的區(qū)別是致燥,find()方法返回查找到的值,findIndex()方法返回查找到的值的索引

let numbers = [25, 30, 35, 40, 45];
console.log(numbers.find(n => n > 33));// 35
console.log(numbers.findIndex(n => n > 33));// 2
  • 這段代碼通過調(diào)用find()方法和findIndex()方法來定位numbers數(shù)組中第一個比33大的值排截,調(diào)用find()方法返回的是35嫌蚤,而調(diào)用findIndex()方法返回的是35在numbeps數(shù)組中的位置2

  • 如果要在數(shù)組中根據(jù)某個條件查找匹配的元素,那么find()方法和findIndex()方法可以很好地完成任務断傲;如果只想查找與某個值匹配的元素脱吱,則indexOf()方法和lastIndexOf()方法是更好的選擇

【fill()】

  • fill()方法可以用指定的值填充一至多個數(shù)組元素。當傳入一個值時认罩,fill()方法會用這個值重寫數(shù)組中的所有值
let numbers = [1, 2, 3, 4];
numbers.fill(1);
console.log(numbers.toString()); // 1,1,1,1
  • 在此示例中箱蝠,調(diào)用numbers.fill(1)方法后numbers中所有的值會變成1,如果只想改變數(shù)組某一部分的值垦垂,可以傳入開始索引和不包含結束索引(不包含結束索引當前值)這兩個可選參數(shù)
let numbers = [1, 2, 3, 4];
numbers.fill(1, 2);
console.log(numbers.toString()); // 1,2,1,1
numbers.fill(0, 1, 3);
console.log(numbers.toString()); // 1,0,0,1
  • numbers.fill(1,2)調(diào)用中宦搬,參數(shù)2表示從索引2開始填充元素,由于未傳入第三個參數(shù)作為不包含結束索引劫拗,因此使用numbers.length作為不包含結束索引间校,因而numbers數(shù)組的最后兩個元素被填充為1。操作numbers.fill(0,1,3)會將數(shù)組中位于索引1和2的元素填充為0页慷。調(diào)用fill()時若傳入第二個和第三個參數(shù)則可以只填充數(shù)組中的部分元素

[注意]如果開始索引或結束索引為負值憔足,那么這些值會與數(shù)組的length屬性相加來作為最終位置。例如酒繁,如果開始位置為-1滓彰,那么索引的值實際為array.length-1array為調(diào)用fill()方法的數(shù)組

【copyWithin()】

??copyWithin()方法與fill()方法相似州袒,其也可以同時改變數(shù)組中的多個元素揭绑。fill()方法是將數(shù)組元素賦值為一個指定的值,而copyWithin()方法則是從數(shù)組中復制元素的值稳析。調(diào)用copyWithin()方法時需要傳入兩個參數(shù):一個是該方法開始填充值的索引位置洗做,另一個是開始復制值的索引位置

  • 比如復制數(shù)組前兩個元素的值到后兩個元素
let numbers = [1, 2, 3, 4];
// 從索引 2 的位置開始粘貼
// 從數(shù)組索引 0 的位置開始復制數(shù)據(jù)numbers.copyWithin(2, 0);
console.log(numbers.toString()); // 1,2,1,2
  • 這段代碼從numbers的索引2開始粘貼值,所以索引2和3將被重寫彰居。給CopyWithin()傳入第二個參數(shù)0表示诚纸,從索引0開始復制值并持續(xù)到?jīng)]有更多可復制的值

  • 默認情況下,copyWithin()會一直復制直到數(shù)組末尾的值陈惰,但是可以提供可選的第三個參數(shù)來限制被重寫元素的數(shù)量畦徘。第三個參數(shù)是不包含結束索引毕籽,用于指定停止復制值的位置

let numbers = [1, 2, 3, 4];
// 從索引 2 的位置開始粘貼
// 從數(shù)組索引 0 的位置開始復制數(shù)據(jù)
// 在遇到索引 1 時停止復制
numbers.copyWithin(2, 0, 1);
console.log(numbers.toString()); // 1,2,1,4
  • 在這個示例中,由于可選的結束索引被設置為了1井辆,因此只有位于索引0的值被復制了关筒,數(shù)組中的最后一個元素保持不變

[注意]正如fill()方法一樣,copyWithin()方法的所有參數(shù)都接受負數(shù)值杯缺,并且會自動與數(shù)組長度相加來作為最終使用的索引

  • fill()copyWithin()這兩個方法起源于定型數(shù)組蒸播,為了保持數(shù)組方法的一致性才添加到常規(guī)數(shù)組中的。如果使用定型數(shù)組來操作數(shù)字的比特萍肆,這些方法將大顯身手

其他章節(jié)

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袍榆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子塘揣,更是在濱河造成了極大的恐慌包雀,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亲铡,死亡現(xiàn)場離奇詭異才写,居然都是意外死亡,警方通過查閱死者的電腦和手機奖蔓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門赞草,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吆鹤,你說我怎么就攤上這事房资。” “怎么了檀头?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岖沛。 經(jīng)常有香客問我暑始,道長,這世上最難降的妖魔是什么婴削? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任廊镜,我火速辦了婚禮,結果婚禮上唉俗,老公的妹妹穿的比我還像新娘嗤朴。我一直安慰自己,他們只是感情好虫溜,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布雹姊。 她就那樣靜靜地躺著,像睡著了一般衡楞。 火紅的嫁衣襯著肌膚如雪吱雏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音歧杏,去河邊找鬼镰惦。 笑死,一個胖子當著我的面吹牛犬绒,可吹牛的內(nèi)容都是我干的旺入。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼凯力,長吁一口氣:“原來是場噩夢啊……” “哼茵瘾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起沮协,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤龄捡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后慷暂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體聘殖,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年行瑞,在試婚紗的時候發(fā)現(xiàn)自己被綠了奸腺。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡血久,死狀恐怖突照,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情氧吐,我是刑警寧澤讹蘑,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站筑舅,受9級特大地震影響座慰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翠拣,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一版仔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧误墓,春花似錦蛮粮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畦娄,卻和暖如春又沾,著一層夾襖步出監(jiān)牢的瞬間弊仪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工杖刷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留励饵,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓滑燃,卻偏偏與公主長得像役听,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子表窘,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

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

  • 原創(chuàng)文章&經(jīng)驗總結&從校招到A廠一路陽光一路滄桑 詳情請戳www.codercc.com 主要知識點:創(chuàng)建數(shù)組典予、數(shù)...
    你聽___閱讀 1,042評論 0 2
  • The JavaScriptArrayobject is a global object thatis used ...
    skycolor閱讀 570評論 0 0
  • 轉(zhuǎn)載:在開發(fā)中瘤袖,數(shù)組的使用場景非常多,平日中也涉及到很多數(shù)組的api/相關操作昂验,一直也沒有對這塊內(nèi)容進行一塊整理總...
    七色煙火閱讀 3,224評論 0 3
  • 第一章:塊級作用域綁定 塊級聲明 1.var聲明及變量提升機制:在函數(shù)作用域或者全局作用域中通過關鍵字var聲明的...
    BeADre_wang閱讀 841評論 0 0
  • 繁忙的周末捂敌,屋外飄著鵝毛大雪,我在家中 有條不紊地打掃整理房間既琴。雖然失去了與白雪親密接觸的機會占婉,但...
    靜若處子閱讀 227評論 2 2