es6-Proxy、Reflect
阿新 • • 發佈:2018-12-13
Proxy
攔截操作、修改物件的預設行為。
// target引數表示要攔截的目標物件,handler引數處理攔截行為。 var proxy = new Proxy(target,handler); var user = { name:'admin', age:'22' } 1.get() var proxy = new Proxy(user,{ get(target,property) { if(property in target){ return target[property]; }else{ throw new ReferenceError("Property \ "+property+" \" does not exist"); } } }); proxy.name; //"admin" proxy.pass; // 丟擲錯誤 // 如果沒有攔截操作,訪問不存在的屬性會返回undefined。 // 實現陣列讀取負數索引 function createArray(...item){ let handler = { get(target,prop,receiver) { let index = Number(prop); if(index < 0){ prop = String(target.length+index); } return Reflect.get(target,prop,receiver); } } let target = []; target.push(...item); return new Proxy(target,handler); } let arr = createArray(3,4,5); arr[2]; //5 arr[-1]; //5 2.set() 利用set方法,可以資料繫結,即物件發生變化時,會自動更新DOM。 let proxy = new Proxy(user,{ set(target,prop,value) { if(prop === 'age'){ if(!Number.isInteger(value)){ throw new TypeError('The age is not an integer'); } if(value>200){ throw new RangeError("The age seems invalid"); } } target[prop] = value; } }); proxy.age; //22 proxy.age = "hello"; //拋處一個錯誤,‘The age is not an integer’ proxy.age = 300; //拋處一個錯誤,‘The age seems invalid’ 3.可攔截操作過濾掉私有屬性,以‘_’為字首的屬性。 > has()/攔截 in 操作符 var handler = { has(target,key) { if(key[0] === '_'){ return false; } return key in target; } } var target = {_name:'admin',name:'xiao li'}; var proxy = new Proxy(target,handler); '_name' in proxy; //false; '_name' in target; //true > enumerate()/攔截for...in迴圈 **未支援 var handler = { enumerate(target) { return Object.keys(target).filter(key=>key[0]!=='_')[Symbol.iterator](); } } var target = {name:'admin',_name:'System',_age:'34'}; var proxy = new Proxy(target,handler); for(let key in proxy){ console.log(key); } //name > getPrototypeOf() 攔截以下操作: Object.getPrototypeOf(); Object.prototype.__proto__; Object.prototype.isPrototypeOf(); Object.getPrototypeOf(); Reflect.getPrototypeOf(); instanceOf運算子
Proxy.revocable() 返回一個可取消的Proxy例項。
let target = {};
let handler = {};
let {proxy,revoke} = Proxy.revocable(target,handler);
proxy.name = "admin";
proxy.name; //"admin"
revoke();
proxy.name; // 拋處錯誤,‘has been revoked’
Proxy是針對Proxy例項進行操作的,訪問原物件不會攔截操作。 Proxy支援的攔截操作的方法和Reflect物件的方法對應。
Reflect
為操作物件提供的新API。 特點:
1.將Object物件上屬於語言層面的方法放到Reflect物件上。 2.修改了Object物件某些方法的返回結果。 3.讓Object一些命令式的操作都變成函式行為, 4.Reflect物件的方法與Proxy物件的方法一一對應。
Reflect物件的方法。
1、 var obj = { name:'hello' } Reflect.getOwnPropertyDescriptor(obj,"name"); /** { configurable:true enumerable:true value:"hello" writable:true } **/ Reflect.defineProperty(obj,"name",{ enumerable:false }); //true Reflect.getOwnPropertyNames (obj); //未支援, Object.getOwnPropertyNames(obj); //"name" 2、某些對應Object的方法,替代 Reflect.has(obj,name); === name in obj Reflect.deleteProperty(obj,name); === delete obj[name] Reflect.construct(target,args); === new target(...args);
物件 | 方法 | 引數 | 描述 |
---|---|---|---|
Reflect | .getOwnPropertyDescriptor | target,name | 獲取目標物件的描述屬性 |
.defineProperty | target,name,desc | 定義屬性的描述物件 | |
.getOwnPropertyNames | target | **未支援 | |
.getPrototypeOf | target | 獲取物件的原型物件 | |
.setPrototypeOf | target,prototype | ||
.deleteProperty | target,name | 刪除物件中的屬性 | |
.enumerate | target | **未支援 | |
.freeze | target | 凍結物件,防止修改 | |
.seal | target | 密封物件,防止刪除 | |
.preventExtensions | target | 防止物件的擴充套件 | |
.isFrozen | target | ||
.isSealed | target | ||
.isExtensible | target | ||
.isPrototypeOf | target | 檢測目標物件是存在於另一個物件的原型鏈上 | |
obj | .propertyIsEnumerable | name | 該屬性是否可列舉 |
.has | target,name | 是否擁有該屬性,返回Boolean | |
.hasOwn | target,name | **未支援 | |
obj | .hasOwnProperty | name | 物件是否包含該屬性 |
.keys | target | **未支援 | |
.ownKeys | target | 返回物件的屬性名 | |
.get | target,name,receiver | ||
.set | target,name,value,receiver | ||
.apply | target,thisArg,args | ||
.construct | target,args | ||
.valueOf | target | 返回物件的原始屬性 | |
.toString |