在陣列中的應用
擴展運算子(spread)是三個點(...),它好比 rest 引數的逆運算,++將一個陣列轉為用逗號分隔的引數序列++,
console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]
擴展運算子與正常的函式引數可以結合使用,非常靈活,
function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);
// ES6的寫法
function f(x, y, z) {
// ...
}
let args = [0, 1, 2];
f(...args);
擴展運算子后面還可以放置運算式,
const arr = [
...(x > 0 ? ['a'] : []),
'b',
];
通過push函式,將一個陣列添加到另一個陣列的尾部,
ES5 寫法中,push方法的引數不能是陣列,所以只好通過apply方法變通使用push方法,有了擴展運算子,就可以直接將陣列傳入push方法,
// ES5的 寫法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6 的寫法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);
通過擴展運算子,生成日期
// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]))
// ES6
new Date(...[2015, 1, 1]);
復制陣列
a1會回傳原陣列的克隆,再修改a2就不會對a1產生影響,
//es5
const a1 = [1, 2];
const a2 = a1.concat();
a2[0] = 2;
a1 // [1, 2]
//es6
const a1 = [1, 2];
// 寫法一
const a2 = [...a1];
// 寫法二
const [...a2] = a1;
合并陣列
這兩種方法都是淺拷貝
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5 的合并陣列
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并陣列
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
與解構賦值結合
如果將擴展運算子用于陣列賦值,只能放在引數的最后一位,否則會報錯,
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []
const [first, ...rest] = ["foo"];
first // "foo"
rest // []
字串
擴展運算子還可以將字串轉為真正的陣列,
[...'hello']
// [ "h", "e", "l", "l", "o" ]
實作了 Iterator 介面的物件
querySelectorAll方法回傳的是一個NodeList物件,它不是陣列,而是一個類似陣列的物件,這時,擴展運算子可以將其轉為真正的陣列,原因就在于NodeList物件實作了 Iterator ,
let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
Map 和 Set 結構,Generator 函式
擴展運算子內部呼叫的是資料結構的 Iterator 介面,因此只要具有 Iterator 介面的物件,都可以使用擴展運算子,比如 Map 結構,
let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
物件的擴展
解構賦值
變數z是解構賦值所在的物件,它獲取等號右邊的所有尚未讀取的鍵(a和b),將它們連同值一起拷貝過來,
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
解構賦值必須是最后一個引數,否則會報錯,
let { ...x, y, z } = someObject; // 句法錯誤
let { x, ...y, ...z } = someObject; // 句法錯誤
解構賦值的拷貝是淺拷貝,解構賦值拷貝的是這個值的參考
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2
拷貝物件
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
let foo = { ...['a', 'b', 'c'] };
foo
// {0: "a", 1: "b", 2: "c"}
合并兩個物件
let ab = { ...a, ...b };
// 等同于
let ab = Object.assign({}, a, b);
如果用戶自定義的屬性,放在擴展運算子后面,則擴展運算子內部的同名屬性會被覆寫掉,
a物件的x屬性和y屬性,拷貝到新物件后會被覆寫掉,
let aWithOverrides = { ...a, x: 1, y: 2 };
// 等同于
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
// 等同于
let x = 1, y = 2, aWithOverrides = { ...a, x, y };
// 等同于
let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
修改現有物件部分的屬性
let newVersion = {
...previousVersion,
name: 'New Name' // Override the name property
};
如果把自定義屬性放在擴展運算子前面,就變成了設定新物件的默認屬性值,
let aWithDefaults = { x: 1, y: 2, ...a };
// 等同于
let aWithDefaults = Object.assign({}, { x: 1, y: 2 }, a);
// 等同于
let aWithDefaults = Object.assign({ x: 1, y: 2 }, a);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/151141.html
標籤:JavaScript
上一篇:npm -i 與npm install -s與-d的區別
下一篇:JS陣列冒泡排序
