1. Proxy 对象是什么?有什么作用?
Proxy 对象用于创建一个对象的代理,从而实 现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等) 。
const p = new Proxy(target, handler)
-
target
要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。 -
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
let obj = {
name: 'Victor',
age: 28
}
obj = new Proxy(obj, {
get(target, key) {
console.log("获取了getter属性");
return target[key];
},
set(target, key, value) {
if (key === "age" && typeof value !== "number") {
throw Error("age字段必须为Number类型");
}
return Reflect.set(target, key, value);
}
})
console.log(obj.name)
obj.age = false
2. Proxy 中Reflect对象的作用?为什么要用Reflect?
Reflect其实是Object对象的衍生,严格来讲,它继承了Object的大部分方法,也在许多地方做了相应的优化:
1. return不返回obj,而是返回true或者false, 这样可以避免Object.defineProperty抛出错误:
2. 更方便的函数操作 :
在ES5中,譬如:
- 要判断一个obj有定义或者继承了属性name, 在ES5中这样判断:name in obj;
- 或者删除一个属性:delete obj[name],虽然这些很好用,很简短明确,但是最好能将这些方法封装起来,统一调用;
而有了Reflect, 它将这些方法一并封装进入该对象中: - Reflect.has(obj, name)
- Reflect.deleteProperty(obj, name);
3. 更加稳定可靠的函数调用:
在ES5中,如果需要调用一个函数f,执行上下文指向obj对象,还有args参数列表,通常是这么写:
f.apply(obj, args)
However, f could be an object that intentionally or unintentionally defines its own apply method. When you really want to make sure that the built-in apply function is called, one typically writes:
然而, 函数f可能会无意中去定义自己的apply方法。所以为了避嫌,可以这么写:
Function.prototype.apply.call(f, obj, args)
而在ES6中,可以将代码缩短:
Reflect.apply(f, obj, args)
4. 调用构造函数时可接受不确定长度的参数列表:
在ES6中可以使用拓展符:
var obj = new F(...args)
但是在ES5,这样根本行不通,如果有了Reflect,就可以这么写:
var obj = Reflect.construct(F, args)
5. 控制访问器或者读取器的this
在ES5中,访问或者定义或对象属性可以这样写:
var name = ... // get property name as a string
obj[name] // generic property lookup
obj[name] = value // generic property update
Relect也能有相应的方法,此外,还令加了一个receiver参数,用于绑定getter和setter的执行上下文:
var name = ... // get property name as a string
Reflect.get(obj, name, wrapper) // if obj[name] is an accessor, it gets run with `this === wrapper`
Reflect.set(obj, name, value, wrapper)
6. 避免直接访问 proto :
ES5提供了 Object.getPrototypeOf(obj),去访问对象的原型;
而ES6提供也提供了Reflect.getPrototypeOf(obj) 和 Reflect.setPrototypeOf(obj, newProto),这个是新的方法去访问和设置对象的原型:
3. 为什么Proxy中的getter和setter函数会有receiver?
为了避免执行上下文指向出错,这里的receiver指的是 Proxy 或者继承 Proxy 的对象