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指向的Student2.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"