JS基礎——Proxy

Proxy 用於修改某些操作的默認行爲(基本操作有屬性查找,賦值,枚舉,函數調用等)。

/*
* target 目標對象(可以是任何類型的對象,包括原生數組,函數,甚至另一個代理)
* handler 一個對象,其屬性是操作對應的自定義代理函數
*/
let p = new Proxy(target, handler);

基本操作

1、get(target, propKey, receiver):攔截對象屬性的讀取

/*
* target 目標對象
* propKey 對象屬性名
* proxy 實例本身(嚴格地說,是操作行爲所針對的對象)
*/
get(target, propKey, receiver)

var obj = {name : 'Lucy'}
var p = new Proxy(obj,{
    get : function(target,key,receive){
        return key === 'name' ? 'Hello '+target[key] : target[key]
    }
})
p.name  //Hello Lucy

需要注意的是,如果一個屬性不可配置(configurable)且不可寫(writable),則 Proxy 不能修改該屬性。

var obj = Object.defineProperties({}, {
  name: {
    value: 'Lucy',
    writable: false,
    configurable: false
  },
});
var p = new Proxy(obj, {
    get : function(target,key){
        return key === 'name' ? 'Hello '+target[key] : target[key]
    }
});
p.name //報錯

2、set: function(obj, prop, value,receive) : 攔截某個屬性的賦值操作

/*
* target 目標對象
* key 屬性名
* value 屬性值
* receive 代理本身
*/
set: function(target, key, value,receive)
var obj = {age : 18}
var p = new Proxy(obj,{
    set : function(target,key,value){
      if(key === 'age'){
        target[key] = Math.min(value,100);    
      }else{
        target[key] = value;    
      }
    }
})
p.age = 101;
p.age // 100
obj.age // 100

3、has(target, key):攔截key in proxy的操作,返回一個布爾值。

4、deleteProperty(target, propKey):攔截delete proxy[propKey]的操作,返回一個布爾值。

5、ownKeys(target):ownKeys方法用來攔截對象自身屬性的讀取操作,返回一個數組。具體來說,攔截以下操作:

  • Object.getOwnPropertyNames() //返回所有屬性
  • Object.getOwnPropertySymbols()
  • Object.keys(proxy) //返回可枚舉屬性
  • for...in循環
var obj = Object.create(null)
Object.defineProperties(obj, {
  '_id': {
    value: 1,
    configurable : true,
    writable : true,
    enumerable : true
  },
  'name': {
    value : 'Lucy',
    configurable : true,
    writable : true,
    enumerable : true
  }
});
Object.getOwnPropertyNames(obj) // ['_id','name']
for(let key in obj){
    console.log(key) //依次輸出_id,name
}

var p = new Proxy(obj,{ 
    ownKeys : function(target){
        return Object.getOwnPropertyNames(target).filter(x => x[0] != '_')
    }
})
Object.getOwnPropertyNames(p) // ['name']
for(let key in p){
    console.log(key) //輸出name
}

6、getOwnPropertyDescriptor(target, propKey):攔截Object.getOwnPropertyDescriptor(proxy, propKey),返回屬性的描述對象。

7、defineProperty(target, propKey, propDesc):返回一個布爾值,攔截以下操作

  • Object.defineProperty(proxy, propKey, propDesc)
  • Object.defineProperties(proxy, propDescs)

8、preventExtensions(target):攔截Object.preventExtensions(proxy),返回一個布爾值。

9、getPrototypeOf(target):攔截Object.getPrototypeOf(proxy),返回一個對象。

10、isExtensible(target):攔截Object.isExtensible(proxy),返回一個布爾值。

11、setPrototypeOf(target, proto):攔截Object.setPrototypeOf(proxy, proto),返回一個布爾值。如果目標對象是函數,那麼還有兩種額外操作可以攔截。

12、apply(target, object, args):攔截 Proxy 實例作爲函數調用的操作,比如

  • proxy(...args)
  • proxy.call(object, ...args)
  • proxy.apply(...)

13、construct(target, args):攔截 Proxy 實例作爲構造函數調用的操作,比如new proxy(...args)。

參考資料:

Proxy MDN
ECMAScript 6入門

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章