本人自學(xué)es6已經(jīng)有一段時(shí)間了,只覺得有些時(shí)候很是枯燥無味, 時(shí)而又覺得在以后的職業(yè)生涯中會(huì)很有用,因?yàn)閑s6的很多方法和集成的定義和方法會(huì)在開發(fā)中遇到的越來越多,近期本人在學(xué)Reflect,把自己的心得以及體會(huì)分享給大家,希望能對(duì)你們有用。
// Reflect對(duì)象與proxy對(duì)象一樣,也是為了操作對(duì)象而提供的新Api
// 目的是1.通過Reflect拿到語(yǔ)言內(nèi)部的方法? 2.修改某些Object方法的返回結(jié)果,讓其變得更合理Object.defineProperty(obj, name, desc)z在無法定義屬性時(shí)會(huì)拋出一個(gè)錯(cuò)誤。而,Reflect則會(huì)返回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對(duì)象的靜態(tài)方法13個(gè)
//1.
//var myObject = {
// foo:1,
// bar:2,
// get baz(){
// return this.foo + this.bar;
// }
//}
//console.log(Reflect.get(myObject, 'baz'))////如果第一個(gè)參數(shù)不是對(duì)象則會(huì)報(bào)錯(cuò)
////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會(huì)觸發(fā)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,導(dǎo)致觸發(fā)Proxy.defineP//roperty攔截。
//var myObject = {
// foo:1
//}
////舊寫法
//'foo' in myObject // true
// Reflect.deleteProperty(obj, name)用于刪除對(duì)象的屬性
// 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方法用于讀取對(duì)象的__proto__屬性,對(duì)應(yīng)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方法用于設(shè)置對(duì)象的__proto__屬性,返回第一個(gè)參數(shù)對(duì)象,對(duì)應(yīng)Object.setPrototypeOf(obj, newProto)。
//const myObj = new FancyThing();
// 舊寫法
//Object.setPrototypeOf(myObj, OtherThing.prototype);
// 新寫法
//Reflect.setPrototypeOf(myObj, OtherThing.prototype);
// 如果第一個(gè)參數(shù)不是對(duì)象,Object.setPrototypeOf會(huì)返回第一個(gè)參數(shù)本身,而Reflect.setPrototypeOf會(huì)報(bào)錯(cuò)。
//如果第一個(gè)參數(shù)不是對(duì)象
//Reflect.getPrototypeOf(1);// 報(bào)錯(cuò)
//Object.getPrototypeOf(1); //1
//Reflect.setPrototypeOf(1, {})//TypeError: Reflect.setPrototypeOf called on non-object
//Object.setPrototypeOf(1, {}) //1
//如果第一個(gè)參數(shù)是undefind或者是null? 兩者都會(huì)報(bào)錯(cuò)
//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對(duì)象可以簡(jiǎn)化這種操作。
//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? 用來定義對(duì)象的屬性 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())
//注意如果第一個(gè)參數(shù)不是對(duì)象,就會(huì)拋出錯(cuò)誤,比如
// Reflect.defineProperty(1, 'foo')
// Reflect.defineProperty(target, propertyKey, attributes)基本等同于Object.getOwnPropertyDescriptor,用于得到指定屬性的描述對(duì)象,將來會(huì)替代掉后者
// 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的一個(gè)區(qū)別是,如果第一個(gè)參數(shù)不是對(duì)象,Object.getOwnPropertyDescriptor(1, 'foo')不報(bào)錯(cuò),返回undefined,而Reflect.getOwnPropertyDescriptor(1, 'foo')會(huì)拋出錯(cuò)誤,表示參數(shù)非法。
// Reflect.isExtensible(target) 方法對(duì)應(yīng)Object.isExtensible,返回一個(gè)布爾值,表示當(dāng)前對(duì)象是否可拓展
// const myObj = {};
//舊寫法
// Object.isExtensible(myObj)//true
//新寫法
// Reflect.isExtensible(myObj)//true
// 而:
// 如果參數(shù)不是對(duì)象,Object.isExtensible會(huì)返回false,因?yàn)榉菍?duì)象本來就是不可擴(kuò)展的,而Reflect.isExtensible會(huì)報(bào)錯(cuò)。
// Object.isExtensible(1) // false
// Reflect.isExtensible(1) // 報(bào)錯(cuò)
// Reflect.preventExtensions對(duì)應(yīng)Object.preventExtensions方法,用于讓一個(gè)對(duì)象變?yōu)椴豢蓴U(kuò)展。它返回一個(gè)布爾值,表示是否操作成功。
var obj = {};
//舊寫法
Object.preventExtensions(obj);? //Object {}
//新寫法
Reflect.preventExtensions(myObject)? //true
//如果參數(shù)不是對(duì)象,Object.preventExtensions在 ES5 環(huán)境報(bào)錯(cuò),在 ES6 環(huán)境返回傳入的參數(shù),而Reflect.preventExtensions會(huì)報(bào)錯(cuò)。
// ES5 環(huán)境
Object.preventExtensions(1) // 報(bào)錯(cuò)
// ES6 環(huán)境
Object.preventExtensions(1) // 1
// 新寫法
Reflect.preventExtensions(1) // 報(bào)錯(cuò)
// Reflect.ownkeys(target)方法用于返回對(duì)象的所有屬性,基本等同于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.實(shí)例:使用Proxy實(shí)現(xiàn)觀察者模式
// 觀察者模式(Observer mode)指的是函數(shù)自動(dòng)觀察數(shù)據(jù)對(duì)象,一旦對(duì)象有變化,函數(shù)就會(huì)自動(dòng)執(zhí)行。
const person = observable({
name:'張三',
age:20
})
function print(){
console.log(`${person.name}, ${person.age}`)
}
observe(print);
person.name = '李四'
//輸出
//李四, 20
// 上面代碼中,數(shù)據(jù)對(duì)象person是觀察目標(biāo),函數(shù)print是觀察者。一旦數(shù)據(jù)對(duì)象發(fā)生變化,print就會(huì)自動(dòng)執(zhí)行。
// 下面,使用 Proxy 寫一個(gè)觀察者模式的最簡(jiǎn)單實(shí)現(xiàn),即實(shí)現(xiàn)observable和observe這兩個(gè)函數(shù)。思路是observable函數(shù)返回一個(gè)原始對(duì)象的 Proxy 代理,攔截賦值操作,觸發(fā)充當(dāng)觀察者的各個(gè)函數(shù)。
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;
}
// 上面代碼中,先定義了一個(gè)Set集合,所有觀察者函數(shù)都放進(jìn)這個(gè)集合。然后,observable函數(shù)返回原始對(duì)象的代理,攔截賦值操作。攔截函數(shù)set之中,會(huì)自動(dòng)執(zhí)行所有觀察者。