1、Proxy,顧名思義為『代理』,主要為目標對象創建的」代理對象「,用來對目標對象的默認操作進行攔截,值得注意的是,要想使攔截起作用,必須使用「代理對象」來調用這些默認行為。

(1)set(target,prop,val),對對象屬性的賦值操作進行攔截。

(2)get(target,prop),對對象屬性的訪問進行攔截(「.」訪問與表達式訪問)。

(3)deleteProperty(target,prop),攔截刪除對象屬性的操作

(4)ownkeys(target),攔截對象的getOwnPropertyNames操作

(5)has(target,prop),攔截對對象屬性的「in」操作

(6)defineProperty(target,prop,des)攔截對象的Object.defineProperty操作

(7)getOwnPropertyDescriptor(target)攔截對象的Object.getOwnPropertyDescriptor操作

(8)setPrototypeOf(target)攔截對象的Object.setPrototypeOf操作

(9)getPrototypeOf(target)攔截對象的Object.getPrototypeOf操作

(10)apply(target,thisArgs,args),當目標對象是Function時,攔截方法的調用

(11)contruct(target,args),當目標對象是Function時,攔截被new關鍵字調用創建對象

(12)isExtensiable(target)攔截對象的Object.isExtensiable操作,返回值需要與原對象的isExtensiable的返回值保持一致。

(13)preventExtensions(target)攔截對象的Object.preventExtensions操作,當原對象的isExtensiable值為false時,返回值只能為fasle,否則報錯。

2、Reflect,顧名思義為「映射」,提供了與Proxy一一對應的默認行為,可以作為攔截的基礎,當需要對象的默認行為進行擴展時,在Proxy中可以先通過Reflect調用其默認操作,在添加額外的功能,Reflect中的方法改善了Object中的某些方法。

Demo:

//Proxy 主要在執行一些操作之前執行一些攔截,但是執行攔截操作的不是對象本身而是Proxy對象,所以也正如它字面上的意思『代理』

//Proxy對象的構造函數的形式 Proxy(target,handler) 第一參數為要攔截的目標對象,第二個操作為要攔截對象的屬性,和對應的行為
var person = {name:lixuan,age:21};
var handler = {
get(target,prop){//對於獲取屬性的攔截
return prop===name?hello:target[prop];
},
set(target,prop,value){//對於設置屬性值的攔截
target[prop]=prop===age?(value>18?value:18):value;
return true;
},
has(target,prop){//對於是否含有某個屬性的攔截 in 操作
if(prop===age){
console.log(age is hidden!);
return false;
}
return prop in target;
},
getPrototypeOf(target){//攔截Object.getPrototypeOf操作
return {x:1};
},
isExtensible(target){//對於目標對象是否可擴展進行攔截,返回值必須保證和不攔截的時候相等。
console.log(is Extensible!);
return true;
},
ownKeys(target){//對於Object.getOwnPropertyNames的攔截
return [hello,world];
},
setPrototypeOf(target,proto){
throw new Error(Changing the prototype is forbidden);
}
};
var proxy = new Proxy(person,handler);
var fn = function(){};
var proxy_fn = new Proxy(fn,{
apply(target,thisArgs,args){
console.log(this is Proxy);//對於將調用、apply、call時的攔截,目標對象必須是方法
}
});

console.log(proxy.name);//hello 因為之前對獲取屬性的方法進行了攔截,所以返回hello
proxy.age = 12;
console.log(proxy.age);//18 在設置屬性值的時候,進行了攔截,若設置的小於18,則設為18;
proxy_fn();//this is Proxy 對fn方法的調用進行了攔截。
console.log(age in proxy);//age is hidden! false 對判斷是否屬性的操作進行了攔截
console.log(Object.getPrototypeOf(proxy));//{ x: 1 }
console.log(Object.isExtensible(proxy));//is Extensible! true
console.log(Object.getOwnPropertyNames(proxy));//[ hello, world ]
//Object.setPrototypeOf(proxy,{}); //報錯

//Proxy.revocable() 創建一個可取消的Proxy實例 返回值為一個Proxy實例和一個取消方法 我自己當前的編輯器不支持
// var [proxy1,revoke] = Proxy.revocable({name:kermit,age:21},handler);
// console.log(proxy1.age);

//Reflect 主要是將Object上的APIyizhi到Reflect上,以後Object也不會這些方法,也添加和改進了一些原來的方法
//最後Reflect上的行為和Proxy是一一對應的,也就是說Proxy對象中存在的方法,Reflect都有,因此在改變在需要在默認行為中添加額外功能時,
//先調用Reflect中的默認行為,再添加額外的功能,它是Proxy攔截的基礎。

//屬性相關

//獲取屬性的get方法

var lixuan = {name:kermit,age:21}

console.log(Reflect.get(lixuan,name));//kermit

//設置屬性的set方法
Reflect.set(lixuan,name,lixuan);
console.log(Reflect.get(lixuan,name));//lixuan

//刪除屬性的deleteProperty方法
Reflect.deleteProperty(lixuan,age);
console.log(lixuan.age);//undefined

//判斷是否含有某個屬性
console.log(Reflect.has(lixuan,age));//false

//獲取對象的所有屬性
console.log(Reflect.ownKeys(lixuan));//[ name ]

//定義屬性
Reflect.defineProperty(lixuan,sex,{
value:M,
configurable:false
});

console.log(lixuan.sex);//M

//獲取屬性描述符

console.log(Reflect.getOwnPropertyDescriptor(lixuan,sex));
/**
* { value: M,
writable: false,
enumerable: false,
configurable: false }
*/

//原型相關

//設置對象原型
Reflect.setPrototypeOf(lixuan,person);

//獲取對象原型
console.log(Reflect.getPrototypeOf(lixuan));//{ name: lixuan, age: 18 }

//方法有關的

//方法調用
function say(){
console.log(`name:${this.name},age:${this.age}`);
};
Reflect.apply(say,lixuan,[]);//name,lixuan,age:18

//對象相關

//構造方法的調用

function Animal(name){
this.name = name;
}

console.log(Reflect.construct(Animal,[dog]));//Animal { name: dog }

//組織對象擴展(添加新屬性)
Reflect.preventExtensions(lixuan);

//判斷對象是否可擴展
console.log(Reflect.isExtensible(lixuan));//false

以上僅僅是自己對學習的總結,不代表任何觀點。

推薦閱讀:

相关文章