Proxy與Reflect
新建一個代理對象,通過操作代理對象就能操作原對象。Proxy構造函數的兩個參數,一個是需要劫持的對象,一個是操作函數對象。如果不設置操作函數對象,則默認使用Reflect的相關API,也就是說Reflect提供了proxy13種操作函數的默認實現。
const person = {
name:'lf',
age: 19
}
const p = new Proxy(person, {
get(target, property){
return Reflect.get(target, property)
},
set(target, property, value){
target[property] = value
}
})
console.log(p.name) // 'lf'
p.age=23
console.log(p.age) // 23
console.log(person.age) // 23
常用的proxy劫持操作函數以下幾個:
- get(target, propKey, receiver):攔截對象屬性的讀取,比如
proxy.foo
和proxy['foo']
。 - set(target, propKey, value, receiver):攔截對象屬性的設置,比如
proxy.foo = v
或proxy['foo'] = v
,返回一個布爾值。 - has(target, propKey):攔截
propKey in proxy
的操作,返回一個布爾值。 - deleteProperty(target, propKey):攔截
delete proxy[propKey]
的操作,返回一個布爾值。 - ownKeys(target):攔截
Object.getOwnPropertyNames(proxy)
、Object.getOwnPropertySymbols(proxy)
、Object.keys(proxy)
、for...in
循環,返回一個數組。該方法返回目標對象所有自身的屬性的屬性名,而Object.keys()
的返回結果僅包括目標對象自身的可遍歷屬性。 - defineProperty(target, propKey, propDesc):攔截
Object.defineProperty(proxy, propKey, propDesc)
、Object.defineProperties(proxy, propDescs)
,返回一個布爾值。 - getPrototypeOf(target):攔截
Object.getPrototypeOf(proxy)
,返回一個對象。 - apply(target, object, args):攔截 Proxy 實例作爲函數調用的操作,比如
proxy(...args)
、proxy.call(object, ...args)
、proxy.apply(...)
。
對應的Reflect方法:
- Reflect.apply(target, thisArg, args)
- Reflect.get(target, name, receiver) in
- Reflect.set(target, name, value, receiver)
- Reflect.defineProperty(target, name, desc)
- Reflect.deleteProperty(target, name) delete
- Reflect.has(target, name)
- Reflect.ownKeys(target) Object.keys()
- Reflect.getPrototypeOf(target)
Reflect的作用:
原來判斷一個對象是否有某屬性 in 現在可以用Reflect.has(target, 'name') 注意對象屬性得是字符串
原來刪除某屬性 delete 現在可以用Reflect.deleteProperty(target, 'name')
原來獲取一個對象的所有屬性 Object.keys() 現在可以用Reflect.ownKeys(target)
綜上,其他的功能請自行使用。Reflect提供了統一的一套操作對象的API
vue3.0與2.0 Object.defineProperty的對比
vue2.0使用Object.defineProperty(target, prop, handler)來劫持對象屬性的相關操作
- 只能劫持對象屬性,需要遍歷對象的所有屬性
- 無法檢測到對象屬性的添加,vue實例初始化後新添加的對象屬性不具備響應式
- Object.defineProperty無法監控到數組下標的變化,導致直接通過數組的下標給數組設置值,不能實時響應,也無法監聽到push等方法,vue中重寫了這些方法來增加setter
3.0 使用es6 proxy來監聽數據的變化
- 可以劫持整個對象
- 對象新增屬性可以實時響應式,可以檢測到數組下標的變化
- 因爲Proxy是ES6新增的屬性,有些瀏覽器還不支持,只能兼容到IE11