本人自学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之中,会自动执行所有观察者。