重學ES6 陣列擴充套件(2)

legendaryedu發表於2019-05-10

方法

Array.from()

Array.from(),將兩類物件轉成真正的陣列:類似陣列的物件可遍歷的物件(包括Map和Set結構)

let arrayLike = {
    '0':'a',
    '1':'b',
    '2':'c',
    length:3
}
//es5寫法
var arr1 = [].slice.call(arrayLike); //['a','b','c']
//es6
let arr2 = Array.from(arrayLike); //['a','b','c']
複製程式碼

常見的類似陣列的物件是DOM操作返回的NodeList集合,以及函式內部的arguments物件,都可以將他們轉化成為真正的陣列。

只要部署了Iterator介面的資料結構,Array.from都能將其轉化為陣列。

擴充套件運算子 ... 也可以將某些資料結構轉化為陣列。

擴充套件元算符背後呼叫的是遍歷介面(symbol.iterator),如果一個物件沒有部署該介面,就無法轉換。Array.from方法還支援類似陣列的物件。類陣列物件,本質只有一點,必須有 length 屬性,因此,任何有length屬性的物件,都可以通過Array.from方法轉為陣列,但是擴充套件運算子無法轉換。

Array.from({ length:3 });
// [ undefined, undefined, undefined]
複製程式碼

相容寫法

const toArray = (()=>{
    Array.from ? Array.from : obj => [].slice.call( obj )
})();
複製程式碼

Array.from還可以接受第二個引數,作用類似於陣列的map方法。用於對每個元素進行處理,將處理後的值放到返回的陣列裡。

Array.from(arrayLike, x => x * x);
//等同
Array.from(arrayLike).map(x => x * x)
複製程式碼

取DOM節點文字內容

let spans = document.querySelectorAll('span.name');
// map
let names1 = Array.prototype.map.call(spans, s => s.textContent);
//Array.from()
let names2 = Array.from(spans, s => s.textContent);
複製程式碼

將陣列中值為 false 的轉化為0

Array.from([1,,2,,3], (n) => n|| 0);
//[1,0,2,0,3]
複製程式碼

將字串轉化為陣列

function countSymbols(string){
    return Array.from(string).length;
}
countSymbols("aaa") //3
複製程式碼

Array.of()

用於將一組值轉化為陣列

Array.of(3,11,8); //[3,11,8]
Array.of(4); //[4]
複製程式碼

這個方法是為了彌補陣列構建函式Array()的不足。因為引數個數不同,導致Array行為有差異。

Array() //[]
Array(3)//[,,,]
Array(3,11,8) //[3,11,8]
複製程式碼

Array.of()基本可以代替Array 或者 new Array,並不存在因為引數不同導致的函式過載。

Array.of() //[]
Array.of(undefined) //[undefined]
Array.of(1) //[1]
Array.of(1,2) //[1,2]
複製程式碼

Array.of 總是返回引數值組成的陣列。如果沒有引數,返回一個空陣列。

Array.of 模擬實現

function ArrayOf(){
    return [].slice.call(arguments)
}
複製程式碼

陣列例項的 copyWithin()

陣列例項copyWithin方法,會在當前陣列內部將指定位置成員複製到其他位置(會覆蓋原有成員),然後返回當前陣列,方法會修改當前陣列

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

target(必選):從該位置開始替換資料

start(可選):從該位置開始讀取資料,預設為0,如果為負值,表示倒數。

end(可選):到該位置停止讀取資料,預設等於陣列長度。如果為負值,表示倒數。

這3個引數都應該是數值,如果不是,會自動轉成數值。

find()和 findIndex()

陣列例項的find,用於找到第一個符合條件的陣列成員。引數是一個回撥函式,所有陣列成員依次執行該回撥函式,直到找到第一個返回值為true的成員,然後返回該成員,如果沒有,則返回 undefined。

[1,4,-5,3].find((n) => n < 0)
// -5
[1,5,10,15].find(function(value,index,arr){ // 當前值,當前值位置,原陣列
    return value > 9;
})
//10
複製程式碼

陣列例項的findIndex用法與find非常相似,返回第一個符合條件的成員位置,如果都不符合,返回 -1

[1,5,10,15].findIndex(function(value,index,arr){
    return value > 9;
})
//2
複製程式碼

fill()

['a','b','c'].fill(7)
// [7,7,7]
new Array(3).fill(7)
// [7,7,7]
複製程式碼

fill還可以接受第二個,第三個引數,指定起始位置和結束位置

['a','b','c'].fill(7,1,2);
// ['a',7,'b']
複製程式碼

entires()、 keys()、 values()

以上三個方法,都返回一個遍歷器物件,可用for...of迴圈遍歷,唯一的區別,keys 是對鍵名的遍歷,values 是對鍵值的遍歷,entires 是對鍵值對的遍歷。

for(let index of ['a','b'].keys()){
    console.log(index)
}
// 0
// 1
複製程式碼
for(let index of ['a','b'].values()){
    console.log(index)
}
// 'a'
// 'b'
複製程式碼
for(let index of ['a','b'].entires()){
    console.log(index,elem)
}
// 0 'a'
// 1 'b'
複製程式碼

還可以手動呼叫遍歷器物件的 next 方法進行遍歷

let letter = ['a','b','c'];
let entires = letter.entires();
console.log(entires.next().value); // [0,'a']
console.log(entires.next().value); // [1,'b']
console.log(entires.next().value); // [2,'c']
複製程式碼

includes()

返回一個布林值,表示某個陣列是否包含給定的值,與字串的includes類似。

[1,2,3].includes(2) //true
[1,2,3].includes(4) //false
[1,2,NaN].includes(NaN) //true
複製程式碼

該方法的第二個參數列示搜尋的起始位置,預設為0.如果第二個引數為負數,表示倒數的位置,如果大於陣列長度,將重置為0.

[1,2,3].includes(3,3); //false
[1,2,3].includes(3,-1); //true
複製程式碼

indexOf方法有兩個缺點

  • 不夠語義化,含義是:找到引數值第一個出現的位置,所以,比較是否不等於 -1 ,不夠直觀。
  • 內部使用 === 進行判斷,會導致誤判。
[NaN].indexOf(NaN) //-1

[NaN].includes(NaN) // true
複製程式碼

下面程式碼用來檢查當前環境是否支援該方法,如果不支援,採用一個簡易的代替版本。

const contains = (()=>
    Array.prototype.includes
        ?(arr,value) => arr.includes(value)
        :(arr,value) => arr.some(el => el === value)
)();
contains(['foo','bar'],'baz'); // false
複製程式碼

Map結構的has用來查詢鍵名。

Set結構has用來查詢值。

陣列的空位

Array(3) //[, , ,]
複製程式碼

注意,空位不是 undefined,一個位置的值等於 undefeated,依然是有值的。空位是沒有任何值的,in 運算子可以說明這一點。

0 in [undefined,undefined,undefined] //true
0 in [, , ,] // false複製程式碼

相關文章