物件的擴充套件運算子

2021-08-16 21:10:46 字數 4147 閱讀 9974

《陣列的擴充套件》一章中,已經介紹過擴充套件運算子(……)

const [a, ...b] = [1, 2, 3];

a // 1

b // [2, 3]

es2018 將這個運算子

引入了物件。

解構賦值:

物件的解構賦值用於從乙個物件取值,相當於將目標物件自身的所有可遍歷的(enumberable),但是尚未讀取的屬性,分配到指定的物件上面。

let  = ;

x // 1

y // 2

z //

上面**中,變數z是解構賦值所在的物件。它獲取等號右邊的所有尚未讀取的鍵(ab),將它們連同值一起拷貝過來。

由於解構賦值要求等號右邊是乙個物件,所以如果等號右邊是undefinednull,就會報錯,因為它們無法轉為物件。

let  = null; // 執行時錯誤

let = undefined; // 執行時錯誤

解構賦值必須是最後乙個引數,否則會報錯。

let  = obj; // 句法錯誤

let = obj; // 句法錯誤

上面**中,解構賦值不是最後乙個引數,所以會報錯。

注意,解構賦值的拷貝是淺拷貝,即如果乙個鍵的值是復合型別的值(陣列,物件,函式)、那麼解構賦值拷貝的是這個值的引用,而不是這個值的副本。

let obj =  };

let = obj;

obj.a.b = 2;

x.a.b //

上面**中,x是解構賦值所在的物件,拷貝了物件obja屬性。a屬性引用了乙個物件,修改這個物件的值,會影響到解構賦值對它的引用。

另外擴充套件運算子的解構賦值,不能複製繼承自原型物件的屬性。

let o1 = ;

let o2 = ;

o2.__proto__ = o1;

let = o2;

o3 //

o3.a // undefined

上面**中,物件o3複製了o2,但是只複製了o2自身的屬性,沒有複製它的原型物件o1的屬性。

下面是另乙個例子:

const o = object.create();

o.z = 3;

let } = o;

x // 1

y // undefined

z // 3

上面**中,變數x是單純的解構賦值,所以可以讀取物件o繼承的屬性;變數yz是擴充套件運算子的解構賦值,只能讀取物件o自身的屬性,所以變數z可以賦值成功,變數y取不到值。

解構賦值的乙個用處,是擴充套件某個函式的引數,引入其他操作。

function basefunction() 

// 使用 x 和 y 引數進行操作

// 其餘引數傳給原始函式

return basefunction(restconfig);

}

上面**中,原始函式basefunction接受ab作為引數,函式

basefunction的基礎上進行了擴充套件,能夠接受多餘的引數,並且保留原始函式的行為。

擴充套件運算子:

物件的擴充套件運算子(……)用於取出引數物件的所有可遍歷屬性,拷貝到當前物件之中。

let z = ;

let n = ;

n //

這等同於使用object.assign方法。

let aclone = ;

// 等同於

let aclone = object.assign({}, a);

上面的例子只是拷貝了物件例項的屬性,如果想完整轉殖乙個物件,還拷貝物件原型的屬性,可以採用下面的寫法。

// 寫法一

const clone1 = ;

// 寫法二

const clone2 = object.assign(

object.create(object.getprototypeof(obj)),

obj);// 寫法三

const clone3 = object.create(

object.getprototypeof(obj),

object.getownpropertydescriptors(obj)

)

上面**中,寫法一的__proto__屬性在非瀏覽器的環境不一定部署,因此推薦使用寫法二和寫法三。

擴充套件運算子可以用於合併兩個物件。

let ab = ;

// 等同於

let ab = object.assign({}, a, b);

如果使用者自定義的屬性,放在擴充套件運算子後面,則擴充套件運算子內部的同名屬性會被覆蓋掉。

let awithoverrides = ;

// 等同於

let awithoverrides = };

// 等同於

let x = 1, y = 2, awithoverrides = ;

// 等同於

let awithoverrides = object.assign({}, a, );

上面**中,a物件的x屬性和y屬性,拷貝到新物件後會被覆蓋掉。

這用來修改現有物件部分的屬性就很方便了。

let newversion = ;
上面**中,newversion物件自定義了name屬性,其他屬性全部複製自previousversion物件。

如果把自定義屬性放在擴充套件運算子前面,就變成了設定新物件的預設屬性值。

let awithdefaults = ;

// 等同於

even if property keys don』t clash, because objects record insertion order:

let awithdefaults = object.assign({}, , a);

// 等同於

let awithdefaults = object.assign(, a);

與陣列的擴充套件運算子一樣,物件的擴充套件運算子後面可以跟表示式。

const obj =  : {}),

b: 2,

};

如果擴充套件運算子後面是乙個空物件,則沒有任何效果。

, a: 1}

// even if property keys don』t clash, because objects record insertion order:

如果擴充套件運算子的引數是nullundefined,這兩個值會被忽略,不會報錯。

let emptyobject = ; // 不報錯
擴充套件運算子的引數物件之中,如果有取值函式get,這個函式是會執行的。

// 並不會丟擲錯誤,因為 x 屬性只是被定義,但沒執行

let awithxgetter =

};// 會丟擲錯誤,因為 x 屬性被執行了

let runtimeerror =

}};

物件擴充套件運算子( )

當編寫乙個方法時,我們允許它傳入的引數是不確定的。這時候可以使用物件擴充套件運算子來作引數,看乙個簡單的列子 12 3456 78functionjspang arg jspang 1,2,3 這時我們看到控制台輸出了 1,2,3,undefined,這說明是可以傳入多個值,並且就算方法中引用多了也...

物件擴充套件運算子( )與rest運算子

當編寫乙個方法時,我們允許它傳入的引數是不確定的。這時候可以使用物件擴充套件運算子來作引數,看乙個簡單的列子 function xzdemo arg xzdemo 1,2,3 這時我們看到控制台輸出了 1,2,3,undefined,這說明是可以傳入多個值,並且就算方法中引用多了也不會報錯。我們先用...

擴充套件運算子

三個點,主要是用來將陣列幻化為用逗號分隔的引數序列。合併陣列 與解構賦值結合 如果將擴充套件運算子用於陣列賦值,只能放在引數的最後一位,否則會報錯。將字串轉為真正的陣列 可以將類似陣列的物件轉為真正的陣列 map和set結構,generator函式 擴充套件運算子內部呼叫的是資料解構的iterato...