擴展運算符
擴展運算符( spread )是三個點( ...)如同 rest 參數的逆運算 將一個數組轉爲用逗號分隔參數序列
console.log(...[1,2,3,4]) // 1 2 3 4
console.log(l , ...[2 , 3 , 4 ], 5 ) // 1 2 3 4 5
// 該運算符主要用於函數調用
function push(array, ... items) {
array.push ( ...items);
}
// 擴展運算符後面還可以放置表達式
const arr = [
...(x > 0 ? ['a'] : [] ),
'b'
]
// 擴展運算符後面是個空數組,則不產生任何效果
[...[], 1] // [1]
替代掉數組的 apply 方法
// 例子1: 函數傳參時傳的是數組的形式
// ES5 的寫法
function f (x, y, z) {
//
var args = [0, 1 , 2] ;
f.apply(null, args) ;
// ES6 的寫法
function f(x, y, z) {
// ...
}
var args = [Q, 1, 2];
f (...args) ;
//例子2: 應用 Math .max 方法簡化求出數組中的最大元素。
// ES5 的寫法
Math .max.apply(null , (14 , 3 , 77])
// ES6 的寫法
Math.max ( ...[14, 3, 77])
// 例子3: 通過 push 函數將一個數組添加到另一個數組的尾部
var arr1 = [0, 1 , 2] ;
var arr2 = [3 , 4, 5];
// ES5寫法
Array.prototype.push.apply(arr1,arr2);
// ES6寫法
arr1.push(...arr2)
擴展運算符的應用
// 合併數組
擴展運算符提供了數組合並的新寫法。
// ESS
[1 , 2].concat(more)
// ES6
[1 , 2 , ...more]
var arr1 = [ ' a ','b'];
var arr2 = [ 'c' ];
var arr3 = [ 'd','e' ] ;
// ES5 的合併數紐
arr1.concat(arr2 , arr3) ; //[ 'a','b ','c','d','e' ]
// ES6 的合併數組
[...arr1, ...arr2, ...arr3] // [ 'a','b ','c','d','e' ]
// 與解構賦值結合
例子1
const [first, .. . rest] = [1 , 2 , 3 , 4 , 5];
first // 1
rest // [2 , 3 , 4 , 5]
例子2
const [first, ...reset] = ['123'];
first // "123"
rest // []
如果將擴展運算符用於數組賦值,則只能將其放在參數的最後一位,否則會報錯。
const [ ... butLast, last]= [1 , 2 , 3 , 4 , 5] ; // 報錯
const [first, .. . middle , last] = [1 , 2 , 3 , 4 , 5] ; // 報錯
const [ butLast, ...last]= [1 , 2 , 3 , 4 , 5] ; // [1] , [2,3,4,5]
Array. from()
用於將兩類對象轉爲真正數組:類似數組的對象和可遍歷的的對象(包括ES6新增的數據結構Set和Map)
// ESS 的寫法
var arrl = [].slice.call(arrayLike); // [ 'a','b','c' ]
// ES6 的寫法
let arr2 = Array.from(arrayLike) ; // [ 'a','b','c' ]
// querySelectorAll 方法返回的是一個類似數組的對象,只有將這個對象轉爲真正的數組,才能使用forEach 方法。
// 只要是部署了 Iterator 接口的數據結構 Array.from 都能將其轉爲數組。
例子1:
Array.from ('hello') // ['h', 'e', 'l', 'l', 'o']
例子2:
let namesSet =new Set ([ 'a ','b'] )
Array.from(nameSet) // ['a', 'b']
Array from 還可以接受第 個參數,作用類似於數組的 map 方法,用來對每個元素進行 處理,將處理後的值放入返回的數組。
如果 map 函數裏面用到了 this 關鍵字,還可以傳入 Array.from 第三個參數,用來綁定this
Array.from(arrayLike, x => x * x)
//等同於
Array.from(arrayLike).map(x => x * x );
Array.from([1 , 2 , 3), (x) => x * x)
// [1 , 4 , 9]
Array from 的第 個參數指定了第二個參數運行的次數。這種特性可以 讓該方法的用法變得非常靈活。
Array. from ( { length: 2 } , () => ’ j ack ’) //[’ jack ’,’jack ’]
Array.from()的另一個應用是,將宇符串轉爲數組,然後返回字符串的長度。因爲它能正確處理各種 Unicode 字符,可以避免 JavaScript 將大於\uFFFF 的 Unicode 字符算作 2個字符 的bug
function countSymbols(string) { return Array.from(string) .length;}
Array.of()
用於將一組值轉換爲數組。
主要目的是彌補數組構造函數 Array ()的不足, 因爲參數個數的不同會導致 Array()的行爲有差異。
Array() 與 Array.of() 設置新數組的區別,
Array.of() 和 ES5方法 Array() 比較
Array.of(3 , 11 , 8) // [3 , 11 , 8]
Array.of(3) // [3]
Array.of(3).length // 1
Array() // []
Array(3) // [ , , , ] 這裏輸出的並不是預想中的結果
Array (3, 11 , 8) // [3 , 11 , 8]
// 參數個數只有1個時,實際上是指定數組的長度。
// 當參數個數不少於2個時,Array()纔會返回由參數組成的新數組。
Array.of 方法可以用下面的代碼模擬實現:
function ArrayOf() {
return [].slice.call(arguments);
}
數組實例的 copyWithin()
數組實例的 copyWithin 方法會在當前數組內部將指定位置的成員複製到其他位置(會覆蓋原有成員),然後返回當前數組。也就是說,使用這個方法會修改當前數組。
Array.prototype.copyWithin(target, start= 0 , end= this.length)
它接受 個參數。
• target (必選〉 :從該位置開始替換數據。
start (可選):從該位置開始讀取數據,默認爲 。如果爲負值,表示倒數。
• end (可選):到該位置前停止讀取數據,默認等於數組長度。如果爲負值,表示倒數。
這3個參數都應該是數值,如果不是,會自動轉爲數值。
[1, 2 , 3 , 4, 5].copyWithin(0, 3) // [4, 5 , 3 , 4, 5 ]
數組實例的 find()和 findIndex()
數組實例的 find 方法用於找出第一個符合條件的數組成員。
它的參數是 個回調函數, 所有數組成員依次執行該回調函數 直到找出第1個返回值爲 true 的成員,然後返回該成員
如果沒有符合條件的成員,則返回 undefined
[1 , 4 , - 5 , 10] .find( (n) => n < 0) // -5
[1 , 5 , 10, 15].find(function (value , index , arr) {
return value > 9;
}) // 10
這兩個方法都可以發現 NaN 彌補了數組的 indexOf 方法的不足。
findindex方法可以借Object.is方法做到。
[NaN].indexOf(NaN) // -1
[NaN].findlndex(y => Object.is(NaN, y)) // 0
數組實例的fill()
fill 方法使用給定值填充 數組。
例子1:
['a','b','c'].fill(7) // [7,7,7]
例子2:
new Array(3).fill (7)
// [7 , 7 , 7]
fill 方法還可以接受第二個和第三個參數 用於指定填充 起始位置和結束位置
上面的代碼表示, fill 方法從1號位開始向原數組填充7,到2號位之前結束。
['a','b','c'].fill(7 , 1 , 2)
//[ 'a', 7 , 'c']
['a','b','c'].fill(7 , 1 , 3)
// ["a", 7, 7]
['a','b','c'].fill(7 , 2 , 3)
// ["a", "b", 7]
數組實例的 entries ()、 keys()和 values() <用於遍歷數組>
可用 for ... of 循環遍歷 唯一的區別在於keys()是對鍵名的遍歷; values ()是對鍵值的遍歷; entries()是對鍵值對的遍歷。
for(let index of [1,2].keys()) {console.log(index)}
// 0 1
for(let index of [1,2].values()) {console.log(index)}
// 1 2
for(let index of [1,2].entries()) {console.log(index)}
// [0, 1] [1, 2]
數組實例的 includes()
Array prototype ncludes 方法返回一個布爾值,表示某個數組是否包含給定的值, 與字符串的 includes 方法類似。
ES2016引入該方法
[1,2,3].includes(2) // true
[1,2,3].include(4) // false
[1,2,NaN].includes(NaN) // true
該方法的第二個參數表示搜索的起始位置 默認爲0 。
如果第二個參數爲負數,則表示倒數的位置
如果這時它大於數組長度(比如第二個參數爲 -4,但數組長度爲 3),則會重置爲從0開始。
[1 , 2 , 3].includes (3, 3) ; // false
[1 , 2 , 3].includes(3, -1); // true
indexOf 方法有兩個缺點 :
一是不夠語義化,其含義是找到參數值的第一個出現位置,所以要比較是否不等於-1 ,表達起來不夠直觀;
二是,其內部使用嚴格相等運算符(===)進行 判斷,會導致對 NaN 的誤判。
[NaN].indexOf(NaN) // -1 即表示不存在
includes 使用的是不一樣的判斷算法:
[NaN].includes(NaN) // true
數組的空位
數組的空位指數組的某個位置沒有任何值。比如,Array 構造函數返回的數組都是空位。
空位不是 undefined ,一個位直的值等於 undefined 依然是有值的 空位是沒有任何 值的, in 運算符可以說明這一點
0 in [undefined, undefined, undefined] // true
0 in [, , , ] // false
第一個數組的0號位置是有值的 第二個數組的0號位置沒有值。
由於空位的處理規則非常不統 ,所以建議避免出現空位。
ES5 對空位的處理很不一致 ,大多數情況下會忽略空位
ES6 則是明確將空位轉爲 undefined !!!
ES5 對空位的處理很不一致 ,大多數情況下會忽略空位
• forEach ()、 filter ()、 every ()和 some ()都會跳過空位。
• map ()會跳過空位,但會保留這個值。
• join ()和 toString ()會將空位視爲 undefined ,而 undefined null 會被處
理成空字符串。
ES6的例子:空位處理
1.Array.from 方法會將數組的空位轉爲 undefined.
Array.from(['a', , 'b']) // ['a', undefined, 'b']
2.擴展運算符( ...)也會將空位轉爲 undefined.
[...['a', ,'b']] // ['a', undefined, 'b']
3. copyWithin() 會連空位一起復制。
[,'a','b', ,].copyWithin(2,0) // [ ,'a', ,'a']
4. fill() 會將空位視爲正常的數組位置。
new Array(3).fill(3) // [3,3,3]
5. for ... of 循環也會遍歷空位,轉換爲undefined
let arr = [ , 'a', ,] // [empty, "a", empty]
for(let i of arr) {
console.log(i) // undefined 'a' undefined
}
6. entries()、 keys()、 values() 、find()和 findindex() 會將空位處理成 undefined