es6 擴充套件運算子後續

2022-08-20 22:36:13 字數 4406 閱讀 8562

擴充套件運算子(...)。es2018 將這個運算子引入了物件。

物件的解構賦值用於從乙個物件取值,相當於將目標物件自身的所有可遍歷的(enumerable)、但尚未被讀取的屬性,分配到指定的物件上面。所有的鍵和它們的值,都會拷貝到新物件上面。

let  = ;

x// 1

y// 2

z//

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

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

let  = null;// 執行時錯誤

let = undefined;// 執行時錯誤

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

let  = someobject;// 句法錯誤

let = someobject;// 句法錯誤

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

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

let obj =  };

let = obj;

obj.a.b = 2;

x.a.b// 2

上面**中,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;

let = newobj;

x// 1

y// undefined

z// 3

上面**中,變數x是單純的解構賦值,所以可以讀取物件o繼承的屬性;變數yz是擴充套件運算子的解構賦值,只能讀取物件o自身的屬性,所以變數z可以賦值成功,變數y取不到值。es6 規定,變數宣告語句之中,如果使用解構賦值,擴充套件運算子後面必須是乙個變數名,而不能是乙個解構賦值表示式,所以上面**引入了中間變數newobj,如果寫成下面這樣會報錯。

let  } = o;// syntaxerror: ... must be followed by an identifier in declaration contexts

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

function basefunction() 

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

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

return basefunction(restconfig);

}

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

let z = ;

let n = ;

n//

由於陣列是特殊的物件,所以物件的擴充套件運算子也可以用於陣列。

let foo = ;

foo//

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

, a: 1}// 

如果擴充套件運算子後面不是物件,則會自動將其轉為物件。

// 等同於 

// {}

上面**中,擴充套件運算子後面是整數1,會自動轉為數值的包裝物件number。由於該物件沒有自身屬性,所以返回乙個空物件。

下面的例子都是類似的道理。

// 等同於 

// {}

// 等同於

// {}

// 等同於

// {}

但是,如果擴充套件運算子後面是字串,它會自動轉成乙個類似陣列的物件,因此返回的不是空物件。

// 

物件的擴充套件運算子等同於使用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 = ;// 等同於

let awithdefaults = object.assign({}, , a);// 等同於

let awithdefaults = object.assign(, a);

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

const obj =  : {}),

b: 2,

};

擴充套件運算子的引數物件之中,如果有取值函式get,這個函式是會執行的。

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

let awithxgetter =

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

let runtimeerror =

}};

ES6 擴充套件運算子

擴充套件運算子用3個點表示,功能是把陣列或者類陣列物件展開成一系列用逗號隔開的值 1,陣列 let arr red green blue console.log arr red,green,blue拷貝陣列 和object.assign一樣都是淺拷貝 let arr red green blue l...

ES6擴充套件運算子

首先,我們要讀仔細下面這句話,就很容易知道擴充套件運算子的使用了,可以在心裡反覆讀三遍 接下來,我們看下究竟怎麼個情況 宣告乙個方法 var foo function a,b,c console.log a console.log b console.log c 宣告乙個陣列 var arr 1,2...

es6擴充套件運算子

1 複製 拷貝 陣列 陣列元素都是基本資料型別 var arr a b c var copy arr console.log copy a b c arr copy false2 函式呼叫 陣列作引數 function add x,y var numbers 4 38 add numbers 423...