《深刻理解ES6》筆記——代理(Proxy)和反射(Reflection)API(12)

反射 Reflect

當你見到一個新的API,不明白的時候,就在瀏覽器打印出來看看它的樣子。前端

clipboard.png

反射的概念

Reflect 是一個內置的對象,它提供可攔截JavaScript操做的方法。方法與代理處理程序的方法相同。Reflect 不是一個函數對象,所以它是不可構造的。webpack

new Reflect() //錯誤的寫法

反射的使用

Reflect提供了一些靜態方法,靜態方法是指只能經過對象自身訪問的的方法,這個知識在前面幾章講解過。全部方法的詳細解析,前往 Reflect詳解 查看。web

靜態方法列表:這麼多靜態方法,你須要學會的是如何使用它們segmentfault

一、Reflect.apply()
二、Reflect.construct()
三、Reflect.defineProperty()
四、Reflect.deleteProperty()
五、Reflect.enumerate()
六、Reflect.get()
七、Reflect.getOwnPropertyDescriptor()
八、Reflect.getPrototypeOf()
九、Reflect.has()
十、Reflect.isExtensible()
十一、Reflect.ownKeys()
十二、Reflect.preventExtensions()
1三、Reflect.set()
1四、Reflect.setPrototypeOf()api

靜態方法的使用:跨域

demo1:使用Reflect.get()獲取目標對象指定key的value。數組

let obj = {
    a: 1
};

let s1 = Reflect.get(obj, "a")
console.log(s1) // 1

demo2:使用Reflect.apply給目標函數floor傳入指定的參數。瀏覽器

const s2 = Reflect.apply(Math.floor, undefined, [1.75]); 
console.log(s2) // 1

進一步理解Reflect

看了上面的例子和方法,咱們知道Reflect能夠攔截JavaScript代碼,包括攔截對象,攔截函數等,而後對攔截到的對象或者函數進行讀寫等操做。app

好比demo1的get()方法,攔截obj對象,而後讀取key爲a的值。固然,不用反射也能夠讀取a的值。函數

再看demo2的apply()方法,這個方法你應該比較瞭解了,和數組中使用apply不一樣的是,Reflect.apply()提供了3個參數,第一個參數是反射的函數,後面2個參數纔是和數組的apply一致。demo2的例子咱們能夠理解成是攔截了Math.floor方法,而後傳入參數,將返回值賦值給s2,這樣咱們就能在須要讀取這個返回值的時候調用s2。

//數組使用apply
const arr = [1, 2, 3]
function a() {
  return Array.concat.apply(null, arguments)
}
const s = a(arr)
console.log(s) // [1, 2 ,3]

其實Reflect的做用和咱們下面要講的Proxy是差很少的。

代理 Proxy

Proxy這個詞相信你已經聽過無數遍了,我曾經寫過一篇webpack使用代理來攔截指定域的API請求,轉發到新的目標URL的文章 webpack中使用proxy。可是注意Proxy和proxy,大小寫字母之間是不一樣的。本章講的是大寫字母開頭的Proxy。

clipboard.png

語法

let p = new Proxy(target, handler);

target:一個目標對象(能夠是任何類型的對象,包括本機數組,函數,甚至另外一個代理)用Proxy來包裝。
handler:一個對象,其屬性是當執行一個操做時定義代理的行爲的函數。

代理的使用

基礎demo:Proxy的demo有不少,咱們只分析基礎demo,主要看new Proxy({}, handler)的操做,指定目標obj對象,而後handler對象執行get()操做,get()返回值的判斷是,若是name是target目標對象的屬性,則返回target[name]的值,不然返回37,最後測試的時候,p.a是對象p的key,因此返回a的value,而p.b不存在,返回37。

const obj = {
  a: 10
}
let handler = {
    get: function(target, name){
        console.log('test: ', target, name)
        // test:  {"a":10} a
        // test:  {"a":10} b
        return name in target ? target[name] : 37
    }
}
let p = new Proxy(obj, handler)
console.log(p.a, p.b) // 10 37

這個例子的做用是攔截目標對象obj,當執行obj的讀寫操做時,進入handler函數進行判斷,若是讀取的key不存在,則返回默認值。

咱們使用一些http-proxy插件或者webpack的時候,有時候須要訪問某個api時,跳轉到指定的url,這種方式也能解決跨域訪問。這種代理模式和Proxy的代理有殊途同歸之妙。可是,別混爲一體了。

module.exports = {
    devServer: {
       proxy: [
           {
                context: "/api/*", //代理API
                target: 'https://www.hyy.com', //目標URL
                secure: false
          }
       ]
    }
}

總結

不管是反射仍是代理,除了他們使用方法不一樣以外,他們所做的事情很是類似,均可以理解成攔截某個東西,而後執行某個函數操做,再返回函數操做的結果。

大部分前端在平常業務需求中,幾乎不多使用到這2個API,實際使用場景還得在之後的開發中慢慢挖掘。

=> 返回文章目錄

相關文章
相關標籤/搜索