1. 前言
es6
中全新設(shè)計(jì)了一個(gè)叫Proxy
的類型,Proxy
這個(gè)詞的原意是代理,用在這里表示由它來”代理“某些操作,可以譯為”代理器“,可以這樣理解:在目標(biāo)對(duì)象之前架設(shè)一層"攔截",外界對(duì)該對(duì)象的訪問,都必須先通過這層攔截 。
舉個(gè)簡(jiǎn)單的例子
比如茅臺(tái)酒的代理,有了這個(gè)代理,我們就不能直接從茅臺(tái)公司拿酒,必須通過這個(gè)代理
代理說多少錢,就是多少錢,代理說沒有就沒有
Proxy
代理的是一個(gè)對(duì)象,這個(gè)對(duì)象被代理之后,我們就不能直接訪問這個(gè)對(duì)象了,必須通過代理訪問。
比如像獲取某個(gè)屬性的值,代理說沒有就沒有,代理想給你返回啥值就返回啥值
Proxy
就是專門為對(duì)象設(shè)置訪問代理器的,無論是讀還是寫都要經(jīng)過代理,通過proxy
就能輕松監(jiān)視對(duì)象的讀寫過程。
2. 使用
如何使用Proxy
監(jiān)視對(duì)象的讀寫過程呢?定義一個(gè)person
對(duì)象,對(duì)象當(dāng)中有一個(gè)name
屬性和height
屬性,然后通過new Proxy
的方式為person
創(chuàng)建一個(gè)代理對(duì)象,此時(shí)proxy
就是為person
對(duì)象設(shè)置的攔截。
Proxy
的構(gòu)造函數(shù)需要2個(gè)參數(shù),一個(gè)是需要代理的目標(biāo)對(duì)象,另一個(gè)是代理的處理對(duì)象,在這個(gè)處理對(duì)象中可以通過get()
方法監(jiān)視對(duì)象屬性的訪問,通過set()
方法監(jiān)視對(duì)象設(shè)置屬性的過程
const person={
name:'zzz',
height:185
}
const proxy=new Proxy(person,{
get(){//監(jiān)視對(duì)象屬性的訪問
},
set(){//監(jiān)視對(duì)象設(shè)置屬性的過程
}
})
3. Proxy 實(shí)例方法
1. get()方法
get
方法是用于攔截某個(gè)屬性的讀取操作,可以接受三個(gè)參數(shù),依次為 目標(biāo)對(duì)象、屬性名和 proxy
實(shí)例本身 (操作行為所針對(duì)的對(duì)象),最后一個(gè)參數(shù)可選。
const proxy=new Proxy(person,{
get(target,propKey){// 目標(biāo)對(duì)象 訪問的屬性名
console.log(target,propKey); // { } , name
},
set(){
}
})
console.log(proxy.name); // zzz
// 第二個(gè)例子
var person = {
name: "張三"
};
var proxy = new Proxy(person, {
get: function(target, propKey) {
if (propKey in target) {
return target[propKey];
} else {
throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
}
}
});
proxy.name // "張三"
proxy.age // 拋出一個(gè)錯(cuò)誤
get()
方法正常的邏輯應(yīng)該是判斷代理目標(biāo)對(duì)象中是否存在訪問的屬性名,存在就返回對(duì)應(yīng)的值,不存在就返回undefined
或者一個(gè)默認(rèn)值
get(target,propKey){
return propKey in target? target[propKey]:'default'
},
//分別打印存在的屬性和不存在的屬性
console.log(proxy.name); //zzz
console.log(proxy.age); //default
2. set()方法
set()
方法用來攔截某個(gè)屬性的賦值操作,可以接受四個(gè)參數(shù),依次為目標(biāo)對(duì)象、屬性名、屬性值和 Proxy 實(shí)例本身,其中最后一個(gè)參數(shù)可選。
set(target,propKey,value){
console.log(target,propKey,value);
}
proxy.sex='男'
控制臺(tái)就會(huì)打印出寫入的屬性和屬性值
set()
方法正常的邏輯應(yīng)該是為代理目標(biāo)設(shè)置指定屬性,在設(shè)置之前先做一些數(shù)據(jù)校驗(yàn),例如屬性名為height,那么那么就要判斷它的是否是一個(gè)數(shù)字,不是就拋出錯(cuò)誤
set(target,propKey,value){
if(propKey=== 'height'){ //判斷屬性名是否為height
if(!Number.isInteger(value)){//判斷是否為整數(shù)
throw new TypeError(`${value} is not an int`)
}
}
target[propKey]=value
}
set
方法的第四個(gè)參數(shù)receiver
,指的是原始的操作行為所在的那個(gè)對(duì)象,一般情況下是proxy
實(shí)例本身
const handler = {
set: function(obj, prop, value, receiver) {
obj[prop] = receiver;
return true;
}
}
const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
proxy.foo === proxy;
3. apply()方法
apply
方法攔截函數(shù)的調(diào)用、call
和 apply
操作
接受三個(gè)參數(shù),分別是 ==目標(biāo)對(duì)象、目標(biāo)對(duì)象的上下文對(duì)象(this
) 和 目標(biāo)對(duì)象的參數(shù)數(shù)組。
var handler = {
apply(target, ctx, args){
return Reflect.apply(...arguments);
}
};
下面代碼中,變量p
是Proxy
的實(shí)例,當(dāng)它作為函數(shù)調(diào)用時(shí)(p()
),就會(huì)被apply
方法攔截,返回一個(gè)字符串。
var target = function(){ return 'I am the target'};
var handler = {
apply: function(){
return 'i am the proxy';
}
}
var p = new Proxy(target, handler);
console.log(p()); // "i am the proxy"
4. 為什么要存在Proxy?
因?yàn)樵贓S6之前,我們使用Object.defineProperty()
來設(shè)置監(jiān)聽器,來監(jiān)聽對(duì)象屬性的獲取和改寫。但是如果其中存在其他的一些操作,我們是無法監(jiān)測(cè)到的,所以為了解決這樣一個(gè)問題,在ES6中增加了Proxy
代理。Proxy
可以幫助我們監(jiān)聽對(duì)象中的操作。
兩者對(duì)比
Object.defineProperty
文章來源:http://www.zghlxwxcb.cn/news/detail-415660.html
let info = {
name: 'dmc',
age: 20
}
Object.defineProperty(info, 'name', {
get() {
console.log('get--獲取info的name值')
return 'dl'
},
set() {
console.log('set--設(shè)置info的name值')
}
})
console.log(info.name) // get--獲取info的name值 dl
info.name = 'dmc' // set--設(shè)置info的name值
Proxy
文章來源地址http://www.zghlxwxcb.cn/news/detail-415660.html
let info = {
name: 'dmc',
age: 20
}
let infoProxy = new Proxy(info, {
get(target, key) {
console.log('獲取對(duì)象屬性')
return target[key]
},
set(target, key, newValue) {
console.log('設(shè)置對(duì)象屬性')
target[key] = newValue
}
})
到了這里,關(guān)于【ES6】阮一峰ES6學(xué)習(xí)(六) Proxy的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!