1. 程式人生 > 其它 >JS高階—10—Proxy類;Reflct物件;響應式原理;

JS高階—10—Proxy類;Reflct物件;響應式原理;

一、Proxy類

1.1概念

proxy最主要的操作是,對物件、函式物件的所有操作做了一個監聽或者說捕獲攔截,然後可以在捕獲器裡定義自己的行為;

1.2Proxy的所有捕獲器

proxy物件比以前的Object.defineProperty()做了很多增強;除了可以監聽物件的setter、getter訪問器,還有其他的操作也可以,比如in、delete等等

in操作符會呼叫proxy物件的has捕獲器;

delete操作符會diaoyongpxoxy

apply()和construct()用於捕獲器用於代理一個函式物件的時候;

當ObjProxy.apply()時,會被apply()捕獲;

當new   ObjProxy()時,會被construct()捕獲;

二、Reflect系統物件

2.1概念 

Reflect是一個系統內建物件,不需要new Reflect()就可以使用了;

為什麼需要REflect系統物件,

1.首先是更規範,

讓Object更加專注當一個建構函式,把對物件的操作都集中在一個單獨的物件Reflect物件中;

我們通過Objcet.prototype.construct可以獲取Object函式物件(不是new Objcet的例項物件,是 const Object = new Function()的函式物件),然後我們可以看到函式物件裡面定義了很多方法,比如我們很熟悉的Objcet.getOwnPropertyDescriptor();

2.其次,可以和proxy結合使用;

我們使用proxy代理物件,就是為了我們對obj物件的操作做一個代理,因為直接修改物件是不好的(Object.defineProperty()),就是直接修改物件,但是目前proxy的捕獲器裡其實還是直接修改物件,比如set訪問器裡還是target[key] = newValue,這個時候我們使用Relect就可以避免;

拿著兩種方式有什麼區別嗎?看著Reflect.set()還更麻煩些。

當然有,

我們知道,有的時候,物件的某些屬性其實是不可以被賦值的,比如說我們凍結一個物件Object.freeze(obj);

Reflect.set()其實可以返回一個boolean值,告訴我們設定值成功或失敗,

但是target[key]= newVAlue就沒有返回值了,我們設定成功與否就很難判別;

2.2Reflect的常見方法

2.3Reflect的construct

 對target進行new操作,然後創建出來一個例項, 但是這個例項的原型constructor指向的是NewTarget 對Person進行new操作,然後創建出來一個例項, 但是這個例項的原型constructor指向的Student

2.4proxy和reflect

我們可以看到proxy和reflect的方法都是一一對應的,所以proxy和reflect可以搭配使用;

但是reflect也是可以單獨使用的;

 

三、Proxy捕獲器和Reflect物件的Reciver引數作用

我們其實只實現了對name屬性的捕獲,並沒有實現對this的捕獲。

像這個例子中,return  this._name中其中呼叫this時走的時obj自己的this,這說明我們的代理不夠完全;

Reflect物件的reciver引數可以改變原有物件的this,原有物件的this本來指向的this,現在就會指向代理物件了;

總結:如果我們的源物件(obj)有setter、getter的訪問器屬性,那麼可以通過receiver來改變裡面的this;

 const obj = {
  _name: "why",
  get name() {
    return this._name
  },
  set name(newValue) {
    this._name = newValue
  }
}

const objProxy = new Proxy(obj, {
  get: function(target, key, receiver) {
    // receiver是創建出來的代理物件
    console.log("get方法被訪問--------", key, receiver)
    console.log(receiver === objProxy)
    return Reflect.get(target, key, receiver)
  },
  set: function(target, key, newValue, receiver) {
    console.log("set方法被訪問--------", key)
    Reflect.set(target, key, newValue, receiver)
  }
})

// console.log(objProxy.name)
objProxy.name = "kobe"

四、響應式原理