本人自學es6已經有一段時間了,只覺得有些時候很是枯燥無味, 時而又覺得在以后的職業生涯中會很有用,因為es6的很多方法和集成的定義和方法會在開發中遇到的越來越多,近期本人在學Reflect,把自己的心得以及體會分享給大家,希望能對你們有用。
// Reflect對象與proxy對象一樣,也是為了操作對象而提供的新Api
// 目的是1.通過Reflect拿到語言內部的方法? 2.修改某些Object方法的返回結果,讓其變得更合理Object.defineProperty(obj, name, desc)z在無法定義屬性時會拋出一個錯誤。而,Reflect則會返回false
?例如:
老寫法
try{
Object.defineProperty(target, property, attributes)
? success
} catch(e){
failure
}
新寫法
if (Reflect.defineProperty(target, property, attributes)) {
success
}else{
failure
}console.log('assign' in Object === Reflect.has(Object, 'assign'))//true
Proxy(target, {
set:function(target, name, value, receiver){
var success = Reflect.set(target, name, value, receiver)
/if (success) {
// log('')
// }
// }
// })
// Reflect對象的靜態方法13個
//1.
//var myObject = {
// foo:1,
// bar:2,
// get baz(){
// return this.foo + this.bar;
// }
//}
//console.log(Reflect.get(myObject, 'baz'))////如果第一個參數不是對象則會報錯
////2.
//var obj = {
// foo:4,
// set bar (value){
// return this.foo = value;
// }
//}
//var myReceiverObject = {
// foo:0
//}
//Reflect.set(obj,'bar', 1, myReceiverObject);
//obj.foo // 4
//myReceiverObject.foo;//1
////注意,Reflect.set會觸發Proxy.defineProperty攔截
//letp = {
// a:'a'
//};
//let handler = {
// det(target, key, value, receiver){
// console.log('set');
// Reflect.set(target, key, value, receiver)
// },
// defineProperty(target,key, attributes){
// console.log('deleteProperty');
// Reflect.defineProperty(target, key, attributes)
// }
//}
//let obj = new Proxy(p, handler);
//obj.a = 'A';
////set
//// defineProperxy
//// 上面代碼中,Proxy.set攔截中使用了Reflect.set,導致觸發Proxy.defineP//roperty攔截。
//var myObject = {
// foo:1
//}
////舊寫法
//'foo' in myObject // true
// Reflect.deleteProperty(obj, name)用于刪除對象的屬性
// const myObj = {foo: 'bar'};
// delete myObj.foo;
// console.log(myObj)
//新寫法
//Reflect.deleteProperty(myObj, 'foo');
//Reflect.construct(target, args)
//function Greeting(name){
// this.name = name;
//}
////new 的寫法
//const instance = new Greeting('張三');
//
//Reflect.deleteProperty(myObj, 'foo');
// Reflect.getPrototypeOf方法用于讀取對象的__proto__屬性,對應Object.getPrototypeOf(obj)。
// Reflect.getPrototypeOf(obj)
// const myObj = new FancyThing();
//舊寫法
// Object.getPrototypeOf(myObj) === FancyThing.prototype;
//新寫法
// Reflect.getPrototypeOf(myObj) === FancyThing.prototype;
// Reflect.setPrototypeOf(obj, newProto)
// Reflect.setPrototypeOf方法用于設置對象的__proto__屬性,返回第一個參數對象,對應Object.setPrototypeOf(obj, newProto)。
//const myObj = new FancyThing();
// 舊寫法
//Object.setPrototypeOf(myObj, OtherThing.prototype);
// 新寫法
//Reflect.setPrototypeOf(myObj, OtherThing.prototype);
// 如果第一個參數不是對象,Object.setPrototypeOf會返回第一個參數本身,而Reflect.setPrototypeOf會報錯。
//如果第一個參數不是對象
//Reflect.getPrototypeOf(1);// 報錯
//Object.getPrototypeOf(1); //1
//Reflect.setPrototypeOf(1, {})//TypeError: Reflect.setPrototypeOf called on non-object
//Object.setPrototypeOf(1, {}) //1
//如果第一個參數是undefind或者是null? 兩者都會報錯
//Object.setPrototypeOf(null, {}) //// TypeError: Object.setPrototypeOf called on null or undefined
//Reflect.setPrototypeOf(null,{})//// TypeError: Reflect.setPrototypeOf called on non-object
//Reflect.apply(func, thisArg, args)
// Reflect.apply方法等同于 Function.prototype.apply.call(func, thisArg, args),采用Reflect對象可以簡化這種操作。
//const ages = [11,33, 12, 54, 18, 96];
//var obj = {}
////舊寫法
//const youngest = Math.min.apply(obj, ages);
//const oldest = Math.max.apply(obj, ages);
//const type = Object.prototype.toString.call(youngest);
//console.log(type)
////新寫法
//const youngest = Reflect.apply(Math.min, Math, ages);
//const oldest = Reflect.apply(Math.max, Math, ages);
//const type = Reflect.apply(Object.prototype.toString, youngest, [])
// Reflect.defineProperty? 用來定義對象的屬性 Reflect.defineProperty(target, propertyKey, attributes)
// function myDate(){
// }
//舊寫法
// Object.defineProperty(myDate, 'now', {
// value:()=>Date.now()
// })
//新寫法17316382398
// Reflect.defineProperty(myDate, 'now', {
// value:()=>Date.now()
// })
// console.log(myDate.now())
//注意如果第一個參數不是對象,就會拋出錯誤,比如
// Reflect.defineProperty(1, 'foo')
// Reflect.defineProperty(target, propertyKey, attributes)基本等同于Object.getOwnPropertyDescriptor,用于得到指定屬性的描述對象,將來會替代掉后者
// var myObject = {};
// Object.defineProperty(myObject, 'hidden', {
// value: true,
// enumerable: true
// })
//舊寫法
// var theDescriptor = Object.getOwnPropertyDescriptor(myObject, 'hidden')
//新寫法
// var theDescriptor = Reflect.getOwnPropertyDescriptor('myObject', 'hidden')
// Reflect.getOwnPropertyDescriptor和Object.getOwnPropertyDescriptor的一個區別是,如果第一個參數不是對象,Object.getOwnPropertyDescriptor(1, 'foo')不報錯,返回undefined,而Reflect.getOwnPropertyDescriptor(1, 'foo')會拋出錯誤,表示參數非法。
// Reflect.isExtensible(target) 方法對應Object.isExtensible,返回一個布爾值,表示當前對象是否可拓展
// const myObj = {};
//舊寫法
// Object.isExtensible(myObj)//true
//新寫法
// Reflect.isExtensible(myObj)//true
// 而:
// 如果參數不是對象,Object.isExtensible會返回false,因為非對象本來就是不可擴展的,而Reflect.isExtensible會報錯。
// Object.isExtensible(1) // false
// Reflect.isExtensible(1) // 報錯
// Reflect.preventExtensions對應Object.preventExtensions方法,用于讓一個對象變為不可擴展。它返回一個布爾值,表示是否操作成功。
var obj = {};
//舊寫法
Object.preventExtensions(obj);? //Object {}
//新寫法
Reflect.preventExtensions(myObject)? //true
//如果參數不是對象,Object.preventExtensions在 ES5 環境報錯,在 ES6 環境返回傳入的參數,而Reflect.preventExtensions會報錯。
// ES5 環境
Object.preventExtensions(1) // 報錯
// ES6 環境
Object.preventExtensions(1) // 1
// 新寫法
Reflect.preventExtensions(1) // 報錯
// Reflect.ownkeys(target)方法用于返回對象的所有屬性,基本等同于Object.getOwnPropertyNames與Object.getOwnPropertySymbols之和。
var myObject = {
foo:1,
bar:2,
[Symbol.for('baz')]:3,
[Symbol.for('bing')]:4
};
//舊寫法
Object.getOwnPropertyNames(myObject); //['foo', 'baz']
Object.getOwnPropertySymbols(myObject);// //[Symbol.for('baz'), Symbol.for('bing')]
//新寫法
Reflect.ownKeys(myObject);// ['foo', 'bar', Symbol.for('baz'), Symbol.for('bing')]
//3.實例:使用Proxy實現觀察者模式
// 觀察者模式(Observer mode)指的是函數自動觀察數據對象,一旦對象有變化,函數就會自動執行。
const person = observable({
name:'張三',
age:20
})
function print(){
console.log(`${person.name}, ${person.age}`)
}
observe(print);
person.name = '李四'
//輸出
//李四, 20
// 上面代碼中,數據對象person是觀察目標,函數print是觀察者。一旦數據對象發生變化,print就會自動執行。
// 下面,使用 Proxy 寫一個觀察者模式的最簡單實現,即實現observable和observe這兩個函數。思路是observable函數返回一個原始對象的 Proxy 代理,攔截賦值操作,觸發充當觀察者的各個函數。
const queueObserves = new set();
const observe = fn =>queueObserves.add(fn);
const observable = obj=>new Proxy(obj, {set});
function set(target, key, value, receiver){
const result = Reflect.set(target, key, value, receiver);
queuedObservers.forEach(obsserver=> obsserver());
return result;
}
// 上面代碼中,先定義了一個Set集合,所有觀察者函數都放進這個集合。然后,observable函數返回原始對象的代理,攔截賦值操作。攔截函數set之中,會自動執行所有觀察者。