擴充套件運算子(...
)。es2018 將這個運算子引入了物件。
物件的解構賦值用於從乙個物件取值,相當於將目標物件自身的所有可遍歷的(enumerable)、但尚未被讀取的屬性,分配到指定的物件上面。所有的鍵和它們的值,都會拷貝到新物件上面。
let = ;
x// 1
y// 2
z//
上面**中,變數z
是解構賦值所在的物件。它獲取等號右邊的所有尚未讀取的鍵(a
和b
),將它們連同值一起拷貝過來。
由於解構賦值要求等號右邊是乙個物件,所以如果等號右邊是undefined
或null
,就會報錯,因為它們無法轉為物件。
let = null;// 執行時錯誤
let = undefined;// 執行時錯誤
解構賦值必須是最後乙個引數,否則會報錯。
let = someobject;// 句法錯誤
let = someobject;// 句法錯誤
上面**中,解構賦值不是最後乙個引數,所以會報錯。
注意,解構賦值的拷貝是淺拷貝,即如果乙個鍵的值是復合型別的值(陣列、物件、函式)、那麼解構賦值拷貝的是這個值的引用,而不是這個值的副本。
let obj = };
let = obj;
obj.a.b = 2;
x.a.b// 2
上面**中,x
是解構賦值所在的物件,拷貝了物件obj
的a
屬性。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
繼承的屬性;變數y
和z
是擴充套件運算子的解構賦值,只能讀取物件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...