es6基礎0x020:代理

0x000 概述

代理嘛,就是請代理人代替自己做某件事,但是和自己不一樣的是代理人可以有自己的行爲,甚至可以做出和預期相違背的行爲。

0x001 栗子

聲明一個普通對象origin,他有一個屬性name

let origin={
    name: 'origin'
}

聲明一個代理對象

let proxy=new Proxy(origin, {
    get: (target, key)=>target[key]+" from proxy",
    set: (target, key, value)=>target[key]="set by proxy "+value
})

此時輸出originproxy,可以發現,proxy擁有和origin一樣的name屬性

console.log(origin) // {name: 'origin'}
console.log(proxy) // Proxy {name: 'origin'}

origin添加age屬性,再輸出,可以發現,originproxy都擁有了age屬性

origin.age=1 
console.log(origin) // {name: 'origin', age: '1'}
console.log(proxy) // Proxy {name: 'origin', age '1'}

那就是代理嗎,當然不是,我們嘗試爲proxy添加屬性

proxy.x=1
console.log(origin) // {name: 'origin', age: '1', x:'set by proxy 1'}
console.log(proxy) // Proxy {name: 'origin', age '1'}

可以發現,雖然originproxy都擁有了x屬性,但是並不是我們賦值的1,而是多了set by proxy 幾個字符串,很明顯,這裏是執行了初始化proxy時傳入的第二個對象的set方法
那如果我們get

console.log(proxy.x) // set by proxy 1
console.log(proxy.x) // set by proxy 1 from proxy

現在很清楚了,proxy就是origin的代理,所有在proxy上的操作都會同步到origin上,而對origin的操作卻不會同步到proxy上,而且proxy還有自己的行爲。

可以這麼想,proxy就是origin的祕書,所有的事務處理都要提交給祕書,祕書有自己的辦事準則,可以直接提交給老闆,也可以拒絕提交,或者添加一些其他的行爲再提交。那這個祕書到底能代理老闆做哪些事呢?

0x002 陷阱

  • 語法

    let p = new Proxy(target, handler);

初始化一個代理需要有兩個參數

  • target:代理目標
  • handle:陷阱,是一個對象,我們的操作就像一隻逃跑的動物,如果獵人在所有可以逃跑的路上全部放滿了陷阱,那我們總是會落入一起一個的。本質就是一個對象,鍵描述我們的操作,值是函數,描述我們的行爲,一共有13種陷阱。

0x003 set:設置屬性

  • 語法:

    set(target, key, value)
    • target: 代理對象
    • `key: 設置的屬性
    • value: 設置的屬性值
  • 栗子:

    let origin={}
    let proxy=new Proxy(origin,{
        set:(target, key, value)=>{
            if(value>5)target[key]=value+10000
        }
    })
    proxy.x=1
    proxy.y=10
    console.log(proxy) // Proxy {y: 10010}
    console.log(origin) // {y: 10010}
  • 說明:
    上面我們放置了一個set陷阱,當我們做set操作的時候,就會被捕捉到,我們判斷value是否大於5,如果不大於5我們就不會做任何東西,但是如果大於5,就會給做賦值操作,並且還將他加上了10000。上面的栗子就相當於一個攔截器了。

0x004 get:訪問屬性

  • 語法:

    get(target, key)
    • target: 代理對象
    • `key: 訪問的屬性
  • 栗子:

    let origin={
        x:1,
        y:2
    }
    let proxy=new Proxy(origin,{
        get:(target, key)=>{
            if(key==='x')return 'no'
            return target[key]
        }
    })
    console.log(proxy.x) // 'no'
    console.log(proxy.y) // 2

0x005 deleteProperty:刪除屬性

  • 語法:

    deleteProperty(target, key)
    • target: 代理對象
    • `key: 要刪除的屬性
  • 栗子:

    let origin={
        x:1,
        y:2
    }
    let proxy=new Proxy(origin,{
        deleteProperty:(target, key)=>{
            if(key==='x')return
            delete target[key]
        }
    })
    delete proxy.x
    delete proxy.y
    console.log(proxy) // {x:1}

0x006 has:判斷是否包含某屬性

  • 語法:

    has(target, key)
    • target: 代理對象
    • `key: 要判斷的屬性
  • 栗子:

    let origin={
        x:1,
        y:2
    }
    let proxy=new Proxy(origin,{
        has:(target, key)=>{
            if(key==='x')return false
            return true
        }
    })
    console.log('x' in proxy) // false
    console.log('y' in proxy) // true

0x007 ownKeys:獲取自身屬性值

  • 語法:

    ownKeys(target)
    • target: 代理對象
  • 栗子:

    let origin={
        x:1,
        y:2
    }
    let proxy=new Proxy(origin,{
        ownKeys:(target)=>{
            return ['y']
        }
    })
    console.log(Object.getOwnPropertyNames(proxy)) // ['y']

0x008 getPrototypeOf:獲取prototype

  • 語法:

    getPrototypeOf(target)
    • target: 代理對象
  • 栗子

    let origin={
        x:1,
        y:2
    }
    let proxy=new Proxy(origin,{
        getPrototypeOf:(target)=>{
            return null
        }
    })
    console.log(Object.getPrototypeOf(p)) // null

0x009 setPrototypeOf:設置prototype

  • 語法:

    setPrototypeOf(target, prototype)
    • target: 代理對象
    • prototype: 要設置的prototype
  • 栗子

    let origin={
        x:1,
        y:2
    }
    let proxy=new Proxy(origin,{
        setPrototypeOf:(target, prototype)=>{
            throw 'no'
        }
    })
    Object.setPrototypeOf(proxy, {}) //  Uncaught no

0x010 defineProperty :設置屬性描述

  • 語法:

    defineProperty(target, prop, descriptor)
    • target: 代理對象
    • prop: 要設置描述的屬性
    • descriptor: 描述
  • 栗子

    let origin={}
    let proxy=new Proxy(origin,{
        defineProperty:(target, prop, descriptor)=>{
            throw 'no'
        }
    })
    Object.defineProperty(proxy, 'x', {configurable: true}) //  Uncaught no

0x011 getOwnPropertyDescriptor :獲取自身屬性描述

  • 語法:

    getOwnPropertyDescriptor(target, prop)
    • target: 代理對象
    • prop: 獲取描述的屬性
  • 栗子

    let origin={}
    let proxy=new Proxy(origin,{
        getOwnPropertyDescriptor:(target, prop)=>{
            throw 'no'
        }
    })
    Object.getOwnPropertyDescriptor(proxy, 'x') //  Uncaught no

0x012 isExtensible:判斷是否可擴展

  • 語法:

    isExtensible(target)
    • target: 代理對象
  • 栗子

    let origin={}
    let proxy=new Proxy(origin,{
        isExtensible:(target)=>{
           return false
        }
    })
    console.log(Object.isExtensible(proxy)); // false

0x013 preventExtensions :阻止擴展

  • 語法:

    preventExtensions(target)
    • target: 代理對象
  • 栗子:

    let origin={}
    let proxy=new Proxy(origin,{
        preventExtensions:(target)=>{
            return false;
        }
    })
    console.log(Object.preventExtensions(proxy)); // Uncaught TypeError: 'preventExtensions' on proxy: trap returned falsish

0x014 construct:構造

  • 語法:

    construct(target, argumentsList, newTarget) 
    • target: 代理對象
    • argumentsList: 參數列表
    • newTarget: 新對象
  • 栗子:

    let Origin=function(){}
    let OriginProxy=new Proxy(Origin,{
      construct: function(target, argumentsList, newTarget) {
          throw 'error'  
      }
    })
    new OriginProxy() // Uncaught error

0x015 apply:調用

  • 語法:

    apply(target, thisArg, argumentsList)
    • target: 代理對象
    • thisArg: 上下文
    • argumentsList: 參數列表
  • 栗子:

    let origin=function(){}
    let proxy=new Proxy(origin,{
      apply: function(target, thisArg, argumentsList) {
        throw 'error'
      }
    })
    origin() // Uncaught error
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章