JavaScript 代理
JavaScript 代理是一种强大的功能,它允许你拦截对象上的操作,并在它们被执行之前或之后执行自定义代码。这使得开发人员能够创建功能强大的、动态的对象,以及更高级别的代码抽象。
JavaScript 代理的主要用途是创建可观察对象、虚拟对象和代理实现。它们允许你将逻辑封装在代理中,并在对象上执行操作时访问对象的属性和方法。代理还可以用于数据验证、缓存和数据重载等功能。
以下是代理的一些示例用法:
-
可观察对象:可以使用代理来创建可观察对象。当观察者对此对象进行访问时,代理被激活,从而触发通知。
-
虚拟对象:代理可以用于创建虚拟对象。虚拟对象是一种懒加载机制,只有在需要时才会加载对象。
-
代理实现:代理可以用于创建代理实现。使用代理来封装对象的访问,可以在不破坏类型安全的情况下修改对象的行为。
JavaScript 代理是一项强大的功能,可以用于创建高级别的对象抽象和引入更高级别的设计模式。它们是一种常见的工具,可以为 JavaScript 应用程序带来许多好处。
JS 代理(Proxy)是 ES6 中新增的特性,它可以拦截对对象的访问和操作,从而可以在对象的基础上增加自定义的行为。
JS 代理的语法
JS 代理的语法如下:
let proxy = new Proxy(target, handler);
其中,target
是要拦截的对象,handler
是一个包含拦截器(即处理程序)的对象。拦截器可以拦截对象的各种操作,例如访问属性、设置属性、调用方法等。
下面是 JS 代理的一些应用示例:
- 访问属性
可以使用代理拦截对对象属性的读取,例如可以在属性读取时输出日志。
let obj = { name: 'Jack', age: 20 };
let proxy = new Proxy(obj, {
get(target, prop) {
console.log(`读取了属性 ${prop}`);
return target[prop];
}
});
console.log(proxy.name); // 输出 "读取了属性 name" 和 "Jack"
console.log(proxy.age); // 输出 "读取了属性 age" 和 20
- 设置属性
可以使用代理拦截对对象属性的设置,例如可以在属性设置时进行验证或记录日志。
let obj = { name: 'Jack', age: 20 };
let proxy = new Proxy(obj, {
set(target, prop, value) {
if (prop === 'age') {
if (value < 0 || value > 120) {
throw new Error('年龄必须在 0 到 120 之间');
}
}
console.log(`设置属性 ${prop} 为 ${value}`);
target[prop] = value;
}
});
proxy.name = 'Tom'; // 输出 "设置属性 name 为 Tom"
proxy.age = 130; // 抛出错误 "年龄必须在 0 到 120 之间"
- 调用方法
可以使用代理拦截对对象方法的调用,例如可以在方法调用前后输出日志。
let obj = {
getName() {
console.log('调用了 getName 方法');
return 'Jack';
},
getAge() {
console.log('调用了 getAge 方法');
return 20;
}
};
let proxy = new Proxy(obj, {
apply(target, thisArg, args) {
console.log(`调用了方法 ${args[0]}`);
return target[args[0]]();
}
});
console.log(proxy.getName()); // 输出 "调用了方法 getName"、"调用了 getName 方法" 和 "Jack"
console.log(proxy.getAge()); // 输出 "调用了方法 getAge"、"调用了 getAge 方法" 和 20
- 拦截器代理
可以使用代理拦截器代理对象,从而可以对被代理对象的所有操作进行拦截。
let obj = {
name: 'Jack',
age: 20,
getName() {
return this.name;
},
getAge() {
return this.age;
}
};
let handler = {
get(target, prop) {
console.log(`读取了属性 ${prop}`);
return target[prop];
},
set(target, prop, value) {
console.log(`设置属性 ${prop} 为 ${value}`);
target[prop] = value;
},
apply(target, thisArg, args) {
console.log(`调用了方法 ${args[0]}`);
return target[args[0]]();
}
};
let proxy = new Proxy(obj, handler);
console.log(proxy.name); // 输出 "读取了属性 name" 和 "Jack"
proxy.name = 'Tom'; // 输出 "设置属性 name 为 Tom"
console.log(proxy.getName()); // 输出 "调用了方法 getName"、"读取了属性 name" 和 "Tom"
代理拦截器方法集合
JS 代理对象的拦截器方法集合由以下方法组成:
-
get(target, property, receiver)
:用于拦截对象属性的读取操作,接收三个参数,分别为目标对象、属性名和代理对象本身,返回值为读取的属性值。 -
set(target, property, value, receiver)
:用于拦截对象属性的赋值操作,接收四个参数,分别为目标对象、属性名、属性值和代理对象本身,返回值为布尔值,表示属性是否赋值成功。 -
has(target, property)
:用于拦截 in 操作符,即判断属性是否存在于对象中,接收两个参数,分别为目标对象和属性名,返回值为布尔值,表示属性是否存在于对象中。 -
deleteProperty(target, property)
:用于拦截 delete 操作符,即删除对象属性,接收两个参数,分别为目标对象和属性名,返回值为布尔值,表示属性是否删除成功。 -
apply(target, thisArg, args)
:用于拦截函数的调用操作,接收三个参数,分别为目标函数、目标函数的 this 值和函数的参数列表,返回值为函数调用的结果。 -
construct(target, args, newTarget)
:用于拦截构造函数的调用操作,接收三个参数,分别为目标构造函数、构造函数的参数列表和代理对象本身,返回值为新创建的对象。 -
getOwnPropertyDescriptor(target, property)
:用于拦截 Object.getOwnPropertyDescriptor(),即获取属性的描述对象,接收两个参数,分别为目标对象和属性名,返回值为属性的描述对象。 -
defineProperty(target, property, descriptor)
:用于拦截 Object.defineProperty() 和 Object.defineProperties(),即定义对象属性,接收三个参数,分别为目标对象、属性名和属性的描述对象,返回值为布尔值,表示属性是否定义成功。 -
getPrototypeOf(target)
:用于拦截 Object.getPrototypeOf(),即获取对象的原型对象,接收一个参数,即目标对象,返回值为对象的原型对象。 -
setPrototypeOf(target, prototype)
:用于拦截 Object.setPrototypeOf(),即设置对象的原型对象,接收两个参数,分别为目标对象和原型对象,返回值为布尔值,表示原型对象是否设置成功。 -
isExtensible(target)
:用于拦截 Object.isExtensible(),即判断对象是否可扩展,接收一个参数,即目标对象,返回值为布尔值,表示对象是否可扩展。 -
preventExtensions(target)
:用于拦截 Object.preventExtensions(),即防止对象扩展,接收一个参数,即目标对象,返回值为布尔值,表示是否防止对象扩展成功。 -
getOwnPropertyNames(target)
:用于拦截 Object.getOwnPropertyNames(),即获取对象的属性名数组,接收一个参数,即目标对象,返回值为属性名数组。 -
ownKeys(target)
:用于拦截 Object.getOwnPropertySymbols()、Object.getOwnPropertyNames() 和 Object.keys(),即获取对象的全部属性名数组,接收一个参数,即目标对象,返回值为属性名数组。 -
apply(target, thisArg, args)
:用于拦截函数的调用操作,接收三个参数,分别为目标函数、目标函数的 this 值和函数的参数列表,返回值为函数调用的结果。
这些拦截器方法可以被用于代理对象的各种操作,以实现对目标对象的更细粒度的控制。
在 JS 代理中,拦截器参数是指在代理的过程中,可以使用的一些参数对象。这些参数对象分为两类:拦截器方法参数和附加参数。