概述
代理和反射相辅相成。要理解代理,得先理解Reflect(反射)。
Reflect是什么?
Reflect是一个内置的js对象(以前没有,ES6才出来的,有兼容问题 ),它提供了一系列方法,可以让开发者通过调用这些方法,访问一些js底层功能。
由于它类似于其他语言的 反射,因此取名为Reflect。
Reflect可以做什么底层功能?
使用Reflect可以实现诸如 属性的赋值与取值、调用普通函数、调用构造函数、判断属性是否存在与对象中 等等功能。
这些功能不是已经存在了嘛?为什么还需要用Reflect实现一次?
有一个重要理念,在ES5就被提出:减少魔法,让代码更纯粹。(功能都以API的形式出现,而不是以特殊的语法来实现)
为什么提出这样的理念? 很大程度是受到函数式编程的影响。
函数式编程:一切都是API。 举例:函数式编程的写法
// 实现 3+1
add(3)(1)
// (3+1)*6
plus(add(3)(1))(6)
ES6进一步贯彻了这种理念,它认为,对属性内存的控制,原型链的修改、函数的调用等等,这些都属于底层实现,属于一种魔法,因此,需要将它们提取出来,形成一个正常的API,并高度聚合到某个对象中,于是,就造就了Reflect对象。
因此,你可以看到Reflect对象中有很多的API都可以使用过去的某种语法或其他API实现。
它里面到底提供了哪些API?
-
Reflect.set(target, propertyKey, value): 设置对象target的属性propertyKey的值为value,等同于给对象的属性赋值
const obj = { a:1, b:2 } // 魔法 obj.a = 3; // Reflect写法 Reflect.set(obj,'a',10) -
Reflect.get(target, propertyKey): 读取对象target的属性propertyKey,等同于读取对象的属性值
const obj = { a:1, b:2 } // Reflect写法 Reflect.get(obj,'a') -
Reflect.apply(target, thisArgument, argumentsList):调用一个指定的函数,并绑定this和参数列表。等同于函数调用
function method(a, b){ console.log("method", a, b); } // 魔法调用 method(3, 4); // Reflect调用 Reflect.apply(method, null, [3, 4]) -
Reflect.deleteProperty(target, propertyKey):删除一个对象的属性
const obj = { a: 1, b: 2 } // 魔法删除 delete obj.a; // Reflect删除 Reflect.deleteProperty(obj, "a"); -
Reflect.defineProperty(target, propertyKey, attributes):类似于Object.defineProperty,不同的是如果配置出现问题,返回false而不是报错
-
Reflect.construct(target, argumentsList):用构造函数的方式创建一个对象
function Test(a, b) { this.a = a; this.b = b; } // 魔法创建对象 const t = new Test(1, 3); // Reflect创建 const t = Reflect.construct(Test, [1, 3]); -
Reflect.has(target, propertyKey): 判断一个对象是否拥有一个属性
const obj = { a: 1, b: 2 } // 魔法判断 console.log("a" in obj); // Reflect判断 console.log(Reflect.has(obj, "a"));