第十二章 Proxy

概述

??Proxy用于修改某些操作的默認(rèn)行為,等同于在語言層面作出修改,所以屬于一種元編程,即對編程語言進(jìn)行編程。
??Proxy可以理解成在目標(biāo)對象前架設(shè)一個(gè)"攔截"層,外界對該對象的訪問都必須先通過這層攔截,因此提供了一種機(jī)制可以對外界的訪問進(jìn)行過濾和改寫,主要用于數(shù)組、對象、方法調(diào)用自身方法時(shí)改變它們的默認(rèn)行為,每一種方法都有對應(yīng)的攔截方法。
??ES6原生提供Proxy構(gòu)造函數(shù),用于生成Proxy實(shí)例。

let proxy = new Proxy(target, handler)

??Proxy對象的所有用法都是上面這種形式,不同的只是handler參數(shù)的寫法,其中,new Proxy()表示生成一個(gè)Proxy實(shí)例,target參數(shù)表示所要攔截的目標(biāo)對象,handler參數(shù)也是一個(gè)對象,用來定制攔截行為。
??handler如果是空對象,表示沒有攔截,訪問handler就等同于訪問target。

Proxy實(shí)例的方法

get()

get方法用于攔截某個(gè)屬性的讀取操作。

let person = {
    name: '張三'
}
let proxy = new Proxy(person, {
    get (target, property) {
         if (property in target) {
             return target[property]
         } else {
              throw new Error('屬性不存在')
         }
     }
})
proxy.name      // '張三'
proxy.age       // '屬性不存在'
set()

set方法用于攔截某個(gè)屬性的賦值操作。

let validator = {
    set (obj, prop, value) {
        if (prop === 'age') {
            if (!Number.isInteger(value)) {
                throw new Error('不是整數(shù)')
            }
            if (value > 200) {
                throw new Error('值不能大于200')
            }
        }
        obj[prop] = value
    }
}
let person = new Proxy({}, validator)
person.age = 100
person.age  // 100
person.age = 'young'    // 不是整數(shù)
person.age = 300   // 值不能大于200
apply()

apply方法攔截函數(shù)的調(diào)用、call和apply操作
apply方法可以接受3個(gè)參數(shù),分別是目標(biāo)對象、目標(biāo)對象的上下文和目標(biāo)對象的參數(shù)數(shù)組。

let twice = {
    apply (target, ctx, args) {
       return Reflict.apply(...arguments) * 2
   }
}
function sum (left, right) {
    return left + right
}
let proxy = new Proxy(sum, twice)
proxy(1, 2)    // 6
proxy.call(null, 5, 6)   // 22
proxy.apply(null, [7, 8])  // 30
Reflict.apply(proxy, null, [9, 10])   // 38

上面的代碼中,每當(dāng)執(zhí)行proxy函數(shù)(直接調(diào)用或call和apply調(diào)用)就會被apply方法攔截,直接調(diào)用Reflict.apply方法也會被攔截。

has()

has方法用來攔截HasProperty操作,即判斷對象是否具有某個(gè)屬性時(shí),這個(gè)方法會生效。典型的操作就是in運(yùn)算符。

let stu1 = {name: '張三', score: 59}
let stu2 = {name: '李四', score: 99}
let handler = {
    has (target, prop) {
        if (prop === 'score' && target[prop] < 60) {
            console.log(`${target.name}不及格`)
            return false
        }
        return prop in target
    }
}
let oproxy1 = new Proxy(stu1, handler)
let oproxy2 = new Proxy(stu2, handler)
'score' in oproxy1
// 張三不及格
// false

'score' in oproxy2
// true
for (let a in oproxy1) {
    console.log(oproxy1[a])
}
// 張三  59

for (let b in oproxy2) {
    console.log(oproxy2[b])
}
// 李四   99

上面代碼中,has攔截只對in循環(huán)有效,對for...in循環(huán)不生效。

construct()

construct方法用于攔截new命令,下面是攔截對象的寫法。這個(gè)方法接收兩個(gè)參數(shù):

  • target:目標(biāo)對象
  • args:構(gòu)建函數(shù)的參數(shù)對象
let P = new Proxy(function () {}, {
    construct: function (target, args) {
        console.log('called:+args.join(',')')
         return {value: args[0] * 10}
      }
   }
)
(new p(1)).value
// 'called: 1'
// 10
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • defineProperty() 學(xué)習(xí)書籍《ECMAScript 6 入門 》 Proxy Proxy 用于修改某...
    Bui_vlee閱讀 704評論 0 1
  • Proxy代理是一個(gè)共通的概念,可以起到攔截的作用。ES6里將Proxy標(biāo)準(zhǔn)化了,提供了Proxy構(gòu)造函數(shù),用來生...
    張歆琳閱讀 10,262評論 1 7
  • 來自深入理解ES6第十二章,由于最近業(yè)務(wù)中經(jīng)常用到,記錄一下 這里內(nèi)容都太學(xué)術(shù)了,有一篇簡單介紹Proxy作用的文...
    NowhereToRun閱讀 1,094評論 0 1
  • 楊倩,焦點(diǎn)講師三期,堅(jiān)持分享554天(2018-7-07) 你以為的就是你以為的嗎? 錯誤安慰類型一:...
    溫心怡然閱讀 91評論 0 0
  • 編碼單位單位換算bit(位)最小單位Byte(字節(jié))一字節(jié)等于8bit,英語表示是1 Byte=8 bitsKB1...
    WorldPeace_hp閱讀 425評論 0 0

友情鏈接更多精彩內(nèi)容