一、屬性的簡潔表示法
ES6
允許在大括號里面直接寫入變量和函數(shù)驱敲,作為對象的屬性和方法。
如下:變量foo
直接寫在大括號宽闲,屬性名就是變量名众眨,屬性值就是變量值。
- 簡寫的對象方法不能用作構(gòu)造函數(shù)容诬,會報錯
const foo = "bar";
const baz = {foo};
console.log(baz); // => {foo:"bar"}
// 等同于
const baz = {foo:foo}
// 自己使用場景
const {dataSource} = this.props;
this.setState({dataSource});
function getPoint() {
const x = 1;
const y = 10;
return {x, y};
}
方法也可以簡寫
const o = {
init(){
console.log('Hello Word!');
}
}
const obj = {
f() {
this.foo = 'bar';
}
};
new obj.f() // 報錯
二娩梨、super 關(guān)鍵字
this
關(guān)鍵字總是指向函數(shù)所在的當(dāng)前對象
super
關(guān)鍵字指向當(dāng)前對象的原型對象
super
表示原型對象時,只能用在對象的方法中览徒,用在其它地方都會報錯
const o = {
h:"Hello"
}
const p = {
h:"Word",
find() {
return super.h
}
}
Object.setPrototypeOf(p, o);
p.find() // "hello"
三狈定、鏈判斷運算符
在編程實務(wù)中,如果讀取對象內(nèi)部的某個屬性,為了安全我們需要判定一下該對象是否存在
var o = {
x:1,
y:2
}
var a = o && o.x ;
// => undefined
var b = o && o.z;
// => undefined
或者使用三元運算符?:
纽什,判斷一個對象是否存在
var a = o ? o.x : 10;
如上兩種方式措嵌,如果層次深判斷起來非常麻煩,因此ES2020
引入了“鏈判斷運算符”?.
- 直接在鏈?zhǔn)秸{(diào)用的時候判斷芦缰,左側(cè)的對象是否
null
或undefined
铅匹,如果是,就不再往下運算饺藤,返回undefined
包斑。
var o = {
x:1,
y:2,
z:{
w:3
}
}
var a = o?.z?.w;
使用這個運算符,有幾個注意點:
1涕俗、短路機制
a?.[++x];
// 等同于
a == null ? undefined : a[++x];
如果a
是undefined
或null
罗丰,那么x
不會進(jìn)行遞增運算,也就是說再姑,鏈判斷運算符一旦為真萌抵,右側(cè)的表達(dá)式就不再求值。
2元镀、delete
運算符
delete a?.b
// 等同于
a == null ? undefined ? delete a.b;
3绍填、括號的影響
如果屬性鏈有圓括號,鏈判斷運算符對圓括號外部沒有影響栖疑,只對圓括號內(nèi)部有影響讨永。
(a?.b).c
// 等同于
(a == null ? undefined : a.b).c
4、報錯場合(以下寫法是禁止的)
// 構(gòu)造函數(shù)
new a?.()
new a?.b()
// 鏈判斷運算符的右側(cè)有模板字符串
a?.`遇革`
a?.b`{c}`
// 鏈判斷運算符的左側(cè)是 super
super?.()
super?.foo
// 鏈運算符用于賦值運算符左側(cè)
a?.b = c
5卿闹、右側(cè)不得為十進(jìn)制數(shù)值
為了兼容以前代碼,?.
后邊緊跟一個十進(jìn)制的數(shù)組萝快,那么?.
不再被看成一個完整的運算符锻霎,而會按照三元運算符進(jìn)行處理,那個小數(shù)點會歸屬后面的十進(jìn)制數(shù)字揪漩,形成一個小數(shù)旋恼。
a?.3:0
// 被解析成
a ? .3 : 0
四、Null 判斷運算符
讀取對象屬性的時候奄容,如果某個屬性值是null
或undefined
冰更,有時候需要為它們指定默認(rèn)值,常見的做法是通過||
運算符指定默認(rèn)值嫩海。
var o = {
x:0,
t:"",
s:false
}
var a = o.x || 200; // => 200
var b = o.t || "word"; // => "word"
var c = o.s || true; // => true
上述三行代碼都是通過||
運算符指定默認(rèn)值冬殃,但是這樣寫是錯誤的囚痴,開發(fā)者的意愿是叁怪,只要屬性的值為null
或undefined
,默認(rèn)值就會生效深滚,但是如果屬性值為0
或空字符或false
奕谭,默認(rèn)值也會生效涣觉。
為了避免上述情況,ES2020
引入了一個新的Null判斷運算符?
它的行為類似||
血柳,但是只有運算符左側(cè)的值為null
或undefined
官册,才會返回右側(cè)的值。
var a = o.x ?? 200; // => 0
var b = o.t ?? "word"; // => ""
var c = o.s ?? true; // => false
??
有一個運算符優(yōu)先級問題难捌,它與&&
和||
的優(yōu)先級孰高孰低膝宁?現(xiàn)在的規(guī)則是,如果多個邏輯運算符一起使用根吁,必須用括號表明優(yōu)先級员淫,否則會報錯。
五击敌、對象新增方法
1介返、Object.is()
ES6
提出同值相等算法,在所有環(huán)境中沃斤,只要兩個值是一樣的圣蝎,它們就應(yīng)該相等,Object.is()
用來比較兩個值是否嚴(yán)格相等衡瓶,與嚴(yán)格比較運算符===
的行為基本一致徘公。
var o = {
x:0,
y:0
}
Object.is(o.x,o.y); // => true
與===
不同之處在于
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
2、Object.assign()
基本用法
Object.assign
方法用于對象的合并哮针,將源對象的所有可枚舉屬性步淹,復(fù)制到目標(biāo)對象。
- 第一個參數(shù)是目標(biāo)對象
- 后面的參數(shù)都是源對象
var target = {};
var source = {a:1,b:2};
Object.assign(target,source);
target // => {a:1, b:2, c:3}
- 如果目標(biāo)對象與源對象有同名屬性诚撵,或多個源對象有同名屬性缭裆,后面的屬性會覆蓋前面的屬性。
var target = {a:1,c:4};
var source = {a:2,b:3};
Object.assign(target,source);
target // => {a:2,c:4,b:3} 相同的a屬性被覆蓋
- 如果只有一個參數(shù)寿烟,
Object.assign
會直接返回該參數(shù)
var o = {a:1};
Object.is(o,Object.assign(o)); // true
- 如果該參數(shù)不是對象澈驼,則會先轉(zhuǎn)成對象,然后返回
typeof Object.assign(2) // "object"
- 由于undefined和null無法轉(zhuǎn)成對象筛武,所以如果它們作為參數(shù)缝其,直接報錯。
Object.assign(undefined);
Object.assign(null);
// TypeError: Cannot convert undefined or null to object
- 如果非對象參數(shù)出現(xiàn)在源對象的位置徘六,這些參數(shù)會轉(zhuǎn)成對象内边,如果無法轉(zhuǎn)成對象,就會跳過待锈。
var o = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
注意點:
-
淺拷貝
Object.assign()
實現(xiàn)的是淺拷貝漠其,如果源對象的某個屬性值是對象,那么目標(biāo)對象拷貝得到的是這個對象的引用。
var o1 = {a:{b:1}};
var o2 = Object.assign({},o1);
o2.a.b = 2;
o1.a.b; // => 2
- 同名屬性的替換
var target = {a:1,b:2};
var source = {a:"word"};
Object.assign(target,source);
// {a:"word",b:2}
-
數(shù)組的處理
Object.assign()
可以處理數(shù)組和屎,但是會把數(shù)組視為對象拴驮。
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
// 實際執(zhí)行的是
Object.assign({0:1,1:2,2:3},{0:4,1:5});
// 根據(jù)同名替換原則輸出的是:{0:4,1:5,2:3}
Array.from({0:4,1:5,2:3,length:3});
// [4,5,3]
-
取值函數(shù)的處理
Object.assign()
只能進(jìn)行值的復(fù)制,如果要復(fù)制的值是一個取值函數(shù)柴信,那么將求值后再復(fù)制套啤。
var target = {}
var source = {
get x () { return 1 }
}
Object.assign(target,source);
// => {x:1}
常用途徑:
- 為對象添加屬性
class Point {
constructor(x,y){
Object.assign(this,{x,y}); // 屬性的簡潔表示法
}
}
var point = new Point(1,2);
// {x:1,y:2};
point instanceof Point; // => true point 是 類 Point 的實例
point instanceof Object; // => true 所有對象都是Object的實例
-
合并多個對象
將對象合并后返回一個新對象
var o1 = {x:1};
var o2 = {y:2};
var merge = (...sources) => Object.assign({}, ...sources); // 合并函數(shù)
var newObj = merge(o1,o2);
// => {x:1,y:2}
3、__proto__
屬性
__proto__
屬性(前后個兩個下劃線)随常,用來讀取或設(shè)置當(dāng)前對象的prototype
對象潜沦,目前,所有瀏覽器(包括IE11)都部署了這個屬性绪氛。
實現(xiàn)上止潮,__proto__
調(diào)用的是Object.prototype.__proto__
。
該屬性并沒有寫入ES6的正文钞楼,而是附錄喇闸,原因是__proto__
前后的雙下劃線,說明它本質(zhì)是一個內(nèi)部屬性询件,而不是對外的API燃乍。因此,無論是從語義角度宛琅,還是從兼容角度刻蟹,都不要使用,而是用下邊的代替嘿辟。
Object.setPrototypeOf()
(寫入)
Object.getPrototyprOf()
(讀扔弑瘛)
Object.create()
(生成)
Object.setPrototypeOf()
用來設(shè)置一個對象的prototype
對象,返回參數(shù)本身
- 如果第一個參數(shù)是
undefined
或null
红伦,會報錯英古。
// 格式
Object.setPrototypeOf(object, prototype)
// 實際使用
var p = {};
var o = {x:1};
Object.setPrototypeOf(o,p); // 將p對象設(shè)置為o對象的原型
p.y = 2;
p.z = 3;
"x" in o; // => true 自有屬性
"y" in o; // => true 繼承原型對象屬性
"z" in o; // => true 繼承原型對象屬性
Object.getPrototypeOf()
用來讀取一個對象的原型對象
- 如果第一個參數(shù)是
undefined
或null
,會報錯昙读。
var p = {x:1};
var o = Object.create(p);
Object.getPrototypeOf(o);
// {x:1}
Object.is(Object.getPrototypeOf(o),p);
// true
4召调、Object.keys()
- 返回數(shù)組
- 數(shù)組成員是參數(shù)對象自身所有可遍歷的屬性的鍵名
- 不返回繼承的屬性
- 可以使用
for ... of
循環(huán)使用
var o = { a:1, b:2 ,c:3};
Object.keys(o); // => ["a","b","c"]
for (let key of Object.keys(o)) {
console.log(key);
}
// => "a"
// => "b"
// => "c"
5、Object.values()
- 返回數(shù)組
- 數(shù)組成員是參數(shù)對象自身所有可遍歷屬性的鍵值
- 不返回繼承屬性
- 可以使用
for ... of
循環(huán)使用
var o = { a:1, b:2 ,c:3};
Object.values(o); // => [1,2,3]
for (let value of Object.values(obj)) {
console.log(value);
}
// => 1
// => 2
// => 3
- 會過濾屬性名為
Symbol
值的屬性
Object.values({ [Symbol()]: 123, foo: 'abc' });
// ['abc']
- 如果參數(shù)是一個字符串
Object.values('abc');
// => ["a","b","c"]
// 字符串會先轉(zhuǎn)成一個類似數(shù)組的對象如下
Object.keys("abc");
// ["0","1","2"];
Object.values({0:"a",1:"b",2:"c"});
- 如果參數(shù)不是對象蛮浑,會先轉(zhuǎn)成對象唠叛,由于數(shù)值和布爾值的包裝對象,都不會為實例添加非繼承的屬性沮稚,所以返回空數(shù)組
Object.values(42); // => []
Object.values(true); // => []
6艺沼、Object.entries()
- 返回一個數(shù)組
- 數(shù)組成員是參數(shù)對象自身所有可編輯屬性的鍵值對數(shù)組
- 其他行為與
Object.values()
基本一致
var o = { a:1, b:2 ,c:3};
Object.entries(o);
// => [["a",1],["b",2],["c",3]]
for (let [key, value] of entries(o)) {
console.log([key, value]);
}
// => ['a', 1]
// => ['b', 2]
// => ['c', 3]
7、Object.fromEntries()
此方法是Object.entries()
的逆操作蕴掏,用于將一個鍵值對數(shù)組轉(zhuǎn)為對象障般。
Object.fromEntries([["a",1],["b",2],["c",3]]);
// { a:1, b:2 ,c:3}
- 將Map結(jié)構(gòu)轉(zhuǎn)為對象
var map = new Map().set("a",1).set("b",2);
Object.fromEntries(map);
// {a:1,b:2}
- 配合
URLSearchParams
對象调鲸,將查詢字符串轉(zhuǎn)為對象
Object.fromEntries(new URLSearchParams('a=1&b=2'))
// { a: "1", b:"2" }
Object.fromEntries(new URLSearchParams(window.location.search))