什么是proxy
es6提供了一些新特性,其中就有Proxy构造函数,用来生成Proxy实例的,它是一种拦截器。可以理解成,在目标对象之前假设一层”拦截“,外界对该对象饿访问,都必须先通过这层拦截。Proxy提供了一些方法,可以对外界的访问进行过滤和改写。
如何使用Proxy
ES6提供了Proxy 构造函数,用来生成 Proxy 实例。
var proxy = new Proxy(target, handler);
Proxy接受两个参数。第一个参数(target)是所要代理的目标对象, 即如果没有Proxy的介入,操作原来要访问的就是这个对象;第二个参数(handler)是一个配置对象, 对于每一个被代理的操作,需要提供一个对应的处理函数,该函数将拦截对应的操作。
例子
// 创建一个普通对象
const targetObject = {
name: "John",
age: 30,
};
// 创建一个Proxy对象
const proxyObject = new Proxy(targetObject, {
// 拦截读取属性的操作
get: function (target, property) {
console.log(`Getting value of ${property}`);
return target[property];
},
// 拦截设置属性的操作
set: function (target, property, value) {
console.log(`Setting ${property} to ${value}`);
target[property] = value;
},
// 拦截删除属性的操作
deleteProperty: function (target, property) {
console.log(`Deleting property ${property}`);
delete target[property];
},
});
// 使用Proxy对象
console.log(proxyObject.name); // 会触发get拦截,输出 "Getting value of name"
proxyObject.age = 31; // 会触发set拦截,输出 "Setting age to 31"
console.log(proxyObject.age); // 会触发get拦截,输出 "Getting value of age"
delete proxyObject.age; // 会触发deleteProperty拦截,输出 "Deleting property age" console.log(proxyObject.age); // 访问被删除的属性,输出 "undefined"
Proxy 实例的一些常用方法
get:用于拦截对象的读取操作。当读取对象的属性时,会调用 get,并返回相应的值。set:用于拦截对象的设置操作。当设置对象的属性时,会调用 set,并将相应的值传递给它。apply:用于拦截函数的调用操作。当调用对象的函数时,会调用 apply,并将相应的参数传递给它。construct:用于拦截 new 操作符。当使用 new 操作符创建对象的实例时,会调用 construct,并返回相应的实例。has:用于拦截 in 操作符。当使用 in 操作符判断对象是否包含某个属性时,会调用 has,并返回相应的结果。deleteProperty:用于拦截 delete 操作符。当使用 delete 操作符删除对象的属性时,会调用 deleteProperty,并返回相应的结果。
更多方法详情 请看ES6官网
Proxy的常用场景
1.数据验证
Proxy 对象的一个常见应用场景是数据验证。可以使用set来拦截属性的设置操作,并在设置属性之前验证属性的值是否符合某些条件。 以下是一个简单的示例,展示了如何使用set来验证数据:
let validator = {
set: function(target, prop, value) {
if (prop === 'age') {
if (typeof value !== 'number' || value < 0 || value > 120) {
throw new Error('Invalid age');
}
}
target[prop] = value;
return true;
}
};
let person = new Proxy({}, validator);
person.name = 'John';
person.age = 30;
console.log(person.name); // Output: John
console.log(person.age); // Output: 30
person.age = '30'; // Output: Uncaught Error: Invalid age
当属性名为'age'时,它会验证属性的值是否为数字并且是否在 0 到 120 的范围内。如果不是,它会抛出一个错误。否则,它会将属性设置为相应的值。
2. 虚拟化对象
Proxy 对象的一个常见应用场景是对象虚拟化,可以使用 Proxy 对象来创建由真实数据支持但具有附加功能或行为的虚拟对象。 以下是一个简单的示例,展示了如何使用 Proxy 对象来实现对象虚拟化:
let data = {
name: 'John',
age: 30
};
let handler = {
get: function(target, prop) {
if (prop === 'name') {
return target[prop].toUpperCase();
} else {
return target[prop];
}
},
set: function(target, prop, value) {
if (prop === 'age') {
if (typeof value !== 'number' || value < 0 || value > 120) {
throw new Error('Invalid age');
}
}
target[prop] = value;
return true;
}
};
let person = new Proxy(data, handler);
console.log(person.name); // Output: JOHN
console.log(person.age); // Output: 30
person.age = 31; // Output: 31
person.age = '31'; // Output: Uncaught Error: Invalid age
当使用person对象读取name属性时,会调用handler对象的get,并将属性值转换为大写字母。当设置age属性时,会调用handler对象的set钩子函数,并验证属性的值是否为数字,并且是否在 0 到 120 的范围内。如果不是,它会抛出一个错误。否则,它会将属性设置为相应的值。
3. 数据绑定
Proxy 对象的一个常见应用场景是数据绑定,可以使用 Proxy 对象来创建多个数据之间的绑定,以确保它们在任何时候都保持同步。 以下是一个简单的示例,展示了如何使用 Proxy 对象来实现数据绑定:
let person1 = {
name: 'John',
age: 30
};
let person2 = new Proxy({}, {
get: function(target, prop, receiver) {
return person1[prop];
},
set: function(target, prop, value, receiver) {
person1[prop] = value;
return true;
}
});
console.log(person1.name); // Output: John
console.log(person2.name); // Output: John
person1.name = 'Jane';
console.log(person1.name); // Output: Jane
console.log(person2.name); // Output: Jane
person2.name = 'Jim';
console.log(person1.name); // Output: Jim
console.log(person2.name); // Output: Jim
当使用person2对象读取属性时,会调用handler对象的get钩子函数,并返回 person1 对应的属性值。当设置 person2 对象的属性时,会调用 handler 对象的 set 钩子函数,并将属性的值设置为 person1 对应的属性值。