重要知识点:代办和反射的定义、经常运用的圈套函数、可被打消的代办、将代办对象作为原型运用、将代办作为类的原型
代办与反射
- 代办是什么?
经由过程挪用 new Proxy() ,你可以建立一个代办用来替换另一个对象(被称之为目目的对象) ,这个代办对目的对象举行了假造,因而该代办与该目的对象表面上可以被看成同一个对象来看待。
代办许可你阻拦目的对象上的底层操纵,而这本来是JS引擎的内部才能,阻拦行动适用了一个能响应特定操纵的函数(被称之为圈套);
- 反射是什么?
被Reflect对象所代表的反射接口,是给底层操纵供应默许行动的要领的鸠合,这些操纵是可以被代办重写的。每一个代办圈套都有一个对应的反射要领,每一个要领都与对应的圈套函数同名,而且吸收的参数也与之一致。
建立一个简朴的代办
运用Proxy构建可以建立一个简朴的代办对象,须要通报两个参数:目的对象以及一个处理器,后者是定义一个或多个圈套函数的对象。假如不定义圈套函数,则依旧运用目的对象的默许行动:
let target = {};
let proxy = new Proxy(target, {});
proxy.name = "proxy";
console.log(proxy.name); // "proxy"
console.log(target.name); // "proxy"
target.name = "target";
console.log(proxy.name); // "target"
console.log(target.name); // "target"
运用 set 圈套函数考证属性值
假定你想要建立一个对象,并要求其属性值只能是数值,这就意味着该对象的每一个新增属性都要被考证,而且在属性值不为数值范例时应该抛出毛病。为此你须要定义 set 圈套函数来重写设置属性值时的默许行动,该圈套函数能接收四个参数:
- trapTarget :将吸收属性的对象(即代办的目的对象);
- key :须要写入的属性的键(字符串范例或标记范例);
- value :将被写入属性的值;
- receiver :操纵发作的对象(通常是代办对象)。
Reflect.set() 是 set 圈套函数对应的反射要领,同时也是 set 操纵的默许行动。
Reflect.set() 要领与 set 圈套函数一样,能接收这四个参数,让该要领能在圈套函数内部被方便运用:
let target = {
name: "target"
};
let proxy = new Proxy(target, {
set(trapTarget, key, value, receiver) {
// 疏忽已有属性,防止影响它们
if (!trapTarget.hasOwnProperty(key)) {
if (isNaN(value)) {
throw new TypeError("Property must be a number.");
}
}
// 增加属性
return Reflect.set(trapTarget, key, value, receiver);
}
});
// 增加一个新属性
proxy.count = 1;
console.log(proxy.count); // 1
console.log(target.count); // 1
// 你可认为 name 赋一个非数值范例的值,因为该属性已存在
proxy.name = "proxy";
console.log(proxy.name); // "proxy"
console.log(target.name); // "proxy"
// 抛出毛病
proxy.anotherName = "proxy";
运用 get 圈套函数举行对象外形考证
JS 言语风趣但偶然却令人困惑的特征之一,就是读取对象不存在的属性时并不会抛出毛病,而会把 undefined 看成该属性的值,比方:
let target = {};
console.log(target.name); // undefined
在多半言语中,试图读取 target.name 属性都邑抛出毛病,因为该属性并不存在;但 JS 言语却会运用 undefined 。
对象外形( Object Shape )指的是对象已有的属性与要领的鸠合,因为该属性考证只须在读取属性时被触发,因而只需运用 get 圈套函数。该圈套函数会在读取属性时被挪用,纵然该属性在对象中并不存在,它能接收三个参数:
- trapTarget :将会被读取属性的对象(即代办的目的对象);
- key :须要读取的属性的键(字符串范例或标记范例);
- receiver :操纵发作的对象(通常是代办对象)。
响应的Reflect.get()要领一样具有这三个参数。举行对象外形考证的示例代码:
//import {color,sum,magicNumber} from "./export.js"
import * as example from "./export.js"
console.log(example.color)
console.log(example.magicNumber)
console.log(example.
sum(76, 2))
let proxy = new Proxy({}, {
get(trapTarget, key, receiver) {
if (!(key in receiver)) {
throw new TypeError("Property " + key + " doesn't exist.");
}
return Reflect.get(trapTarget, key, receiver);
}
});
// 增加属性的功用一般
proxy.name = "proxy";
console.log(proxy.name); // "proxy"
// 读取不存在属性会抛出毛病
console.log(proxy.nme); // 抛出毛病
运用 has 圈套函数隐蔽属性
in运算符用于推断指定对象中是不是存在某个属性,假如对象的属性名与指定的字符串或标记值相匹配,那末in运算符就会返回true。不管该属性是对象本身的属性照样其原型的属性。
has圈套函数会在运用in运算符的情况下被挪用,掌握in运算符返回差别的效果,has圈套函数会传入两个参数:
trapTarget:代办的目的对象;
key:属性键;
Reflect.has()要领吸收雷同的参数,并向in运算符返回默许的响应效果,用于返回默许响应效果。
let target = {
name: "target",
value: 42
};
let proxy = new Proxy(target, {
has(trapTarget, key) {
if (key === "value") {
return false;
} else {
return Reflect.has(trapTarget, key);
}
}
});
console.log("value" in proxy); // false
console.log("name" in proxy); // true
console.log("toString" in proxy); // true