Proxy是ES6提供的代理器可以起到攔截作用,寫法形式如 var proxy = new Proxy(target,handler);參數target表示要攔截的目標對象,handler是用來定制攔截行為。
var proxy = new Proxy({},{ get : function (target,property) { return 'This is Proxy!'; } }); console.log(proxy.a); //This is Proxy!
Proxy支持攔截操作一覽:攔截對象的讀(get)或寫(set)、攔截propKey in proxy的操作(has返回布爾值)、攔截刪除(deleteProperty返回一個布爾值)、攔截for(var x in proxy)(enumerate返回一個遍歷器)等等。
set示例代碼
let validator = { set : function (obj,prop,value) { if(prop === 'age'){ if(!Number.isInteger(value)){ throw new TypeError('年齡必須是數字!'); } if( value > 100){ throw new TypeError('請輸入有效年齡'); } }else{ console.log("輸入錯誤!!請檢查"); //輸入錯誤!!請檢查 } obj[prop] = value ; }, }; let person = new Proxy({},validator); console.log(person.sss=100); //100 console.log(person.age=100); //100
下面寫一個在對象內部設置內部屬性防止內部屬性被外部屬性讀或寫。
var ceshi = { get : function (target,key) { test(key,'get'); return target[key]; }, set : function (target,key,value) { test(key,'set'); if(key === 'age'){ if(0<value<100){ console.log(`年齡是${value}`); } if(value>100){ console.log("輸入的年齡無效!!!"); } if(value<0){ console.log("年齡不能為負數"); } }else{ console.log("你傳入的參數不對"); } return true; }, } function test(key,action) { if(key[0] === '_'){ return console.log("你傳入的參數不對,請重新傳入參數"); } } var target = {} ; var proxy = new Proxy(target,ceshi); console.log(proxy.age); //undefined console.log(proxy.age = 20); //年齡是20 20 console.log(proxy.age = 120); //年齡是120 輸入的年齡無效!!! 120 console.log(proxy._age); //undefined
如果想攔截函數的調用那么使用apply()方法,該方法接受三個參數目標對象
var twice = { apply(target,ctx,args){ console.log(args); //[ 1, 2, 3 ] return Reflect.apply(...arguments) * 2; } }; function sum(...arguments) { let add = 0; for (let i = 0; i < arguments.length; i++){ add += parseInt(arguments[i]); } return add; console.log(add); } var proxy = new Proxy(sum,twice); console.log(proxy(1,2,3)+"這個proxy"); //12這個proxy console.log(sum(1,2,3)+'這是sum'); //6這是sum
如果你想取消一個Proxy的示例那么使用revoke()方法,形式是ProxyName.revoke()。
還有其他幾種方法,我這里面就簡單的說下吧,
1.deleteProperty()該方法用於攔截delete操作,如果這個方法返回false或者是拋出錯誤當前屬性就被delete命令刪除
2.defineProperty()該方法攔截了Object.defineProperty操作
3.enumerate()該方法用於攔截for...in循環,注意不可與has()方法弄混(has方法用於攔截in操作符)。
4.has()該方法用於攔截in操作符
5.construct()方法用於攔截new命令
6.getOwnPropertyDescriptor()該方法用於攔截Object.getOwnPropertyDescriptor返回一個屬性描述對象或者是undefined。
7.getPrototypeOf()該方法用於攔截Object.getPrototypeOf()運算符以及一些其他操作。
8.isExtensible()該方法用於攔截Object.isExtensible操作。
9.ownKeys()該方法用於攔截Object.keys()操作。
10.preventExtensions()方法該方法用於攔截Object.preventExtensions()操作。
11.setPrototypeOf()方法該方法用於攔截Object.setPrototypeOf()操作。