Object.defineProperty
Object.defineProperty會在一個對象上添加一個屬性蕴轨,獲者修改一個屬性港谊,截取的是對象的屬性
方法接收三個參數(shù)(obj,key,desc)
屬性描述符的類型有兩種
- 數(shù)據(jù)屬性(Data Properties)描述符(Descriptor)
-
存取屬性(Accessor訪問器 Properties)描述符(Descriptor)
desc
1.數(shù)據(jù)屬性描述符
//在直接定義一個對象,所有的數(shù)據(jù)特性都是為true
var obj = {
name: 'jack',
age: 18,
};
//在使用數(shù)據(jù)描述符時,所有的默認(rèn)特性都是為false
//configurable和enumerable + value和writable
Object.defineProperty(obj, 'address', {
//屬性的值,默認(rèn)為undefined
value: 'ad',
//是否可以配置進行delete關(guān)鍵字進行刪除,
configurable: true,
//可枚舉,進行循環(huán)遍歷時是否可以拿到相應(yīng)的key
enumerable: true,
//屬性是否可以寫入值
writable: true,
});
- 存取描述符
var obj = {
name: 'jack',
age: 18,
_address: 'xxx',
};
//configurable和enumerable + get和set方法
//1.在不想私有屬性被暴露,可以通過數(shù)據(jù)存取描述符進行代理
//2.可以收集依賴,
Object.defineProperty(obj, 'address', {
enumerable: true,
configurable: true,
get: function () {
return this._address; //在訪問address時代理給_address
},
set: function (value) {
return this._address = value; //在設(shè)置新的值時賦值給_address
},
});
obj.address = 'aaa';
console.log(obj.address);
vue2的響應(yīng)式原理就是應(yīng)用了存取描述符,在get時將屬性在哪個地方使用時收集依賴,當(dāng)屬性被改變時,在set方法自動更新在哪個地方使用的屬性值
但是Object.defineProperty設(shè)計的初衷橙弱,不是為了去監(jiān)聽截止一個對象中所有的屬性的歧寺,我們在定義某些屬性的時候,初衷其實是定義普通的屬性棘脐,但是后面我們強行將它變成了數(shù)據(jù)屬性描述符斜筐,其次,如果我們想監(jiān)聽更加豐富的操作蛀缝,比如新增屬性顷链、刪除屬性,那么Object.defineProperty是無能為力的屈梁,所有js在es6的更新的時候加了一個Proxy類
Proxy
在ES6中嗤练,新增了一個Proxy類,這個類從名字就可以看出來在讶,是用于幫助我們創(chuàng)建一個代理的煞抬,也就是說,如果我們希望監(jiān)聽一個對象的相關(guān)操作真朗,那么我們可以先創(chuàng)建一個代理對象(Proxy對象),之后對該對象的所有操作僧诚,都通過代理對象來完成遮婶,代理對象可以監(jiān)聽我們想要對原對象進行哪些操作
const obj = {
name:'jack',
age:18
}
const objproxy =new Proxy(obj)
當(dāng)下次需要操作obj時,可以先操作代理對象
Proxy的set和get捕獲器
get函數(shù)有三個參數(shù):
- target:目標(biāo)對象(偵聽的對象)湖笨;
- property:被獲取的屬性key旗扑;
- receiver:調(diào)用的代理對象
set函數(shù)有四個參數(shù): - target:目標(biāo)對象(偵聽的對象);
- property:將被設(shè)置的屬性key慈省;
- value:新屬性值臀防;
- receiver:調(diào)用的代理對象
Proxy所有捕獲器
Proxy給對象提供了13種捕獲器,在進行代理對象的時候基本上都涵蓋所有的操作边败,利用Proxy進行響應(yīng)式是非常好的選擇
Reflect
Reflect也是ES6新增的一個API袱衷,它是一個對象,字面的意思是反射
主要作用
- 它主要提供了很多操作JavaScript對象的方法笑窜,有點像Object中操作對象的方法
- 比如Reflect.getPrototypeOf(target)類似于 Object.getPrototypeOf()
- 比如Reflect.defineProperty(target, propertyKey, attributes)類似于Object.defineProperty()
和Object是類似的致燥,但是為什么還要新增一個呢,這是因為在早期的ECMA規(guī)范中沒有考慮到這種對 對象本身 的操作如何設(shè)計會更加規(guī)范排截,所以將這些API放到了Object上面嫌蚤,為了規(guī)范在es6中新增了Reflect類辐益,可以去看一下Object和Reflect的區(qū)別
Reflect的常見方
Reflect的使用
一般都是在set中傳入數(shù)據(jù),然后直接將newValue賦值給val
const objProxy = new Proxy(obj,{
set(targrt,key,newValue){
return target[key] = newValue
}
})
但是這種直接操作是在原對象上直接操作數(shù)據(jù)的脱吱,本來是用了一個對象代理智政,但是在操作數(shù)據(jù)的時候還是操作原對象的,為了能夠不直接更改原數(shù)據(jù)箱蝠,這里可以利用reflect將數(shù)據(jù)進行一個代理续捂,就像下面的這樣使用