深入理解 ES6 Proxy 实例方法,掌握对象操作的精髓
2023-12-29 16:15:29
ES6 Proxy 实例方法概述
ES6 Proxy 实例方法为 JavaScript 提供了强大的对象操作能力,它允许你截获和修改对象的各种操作,从而实现对象的自定义行为。
Proxy 实例方法主要包括以下几种:
- get:当读取某个属性时触发。
- set:当写入某个属性时触发。
- has:当使用 in 操作符检查属性是否存在时触发。
- deleteProperty:当使用 delete 操作符删除属性时触发。
- getPrototypeOf:当使用 Object.getPrototypeOf() 获取对象的原型时触发。
- setPrototypeOf:当使用 Object.setPrototypeOf() 设置对象的原型时触发。
- preventExtensions:当使用 Object.preventExtensions() 尝试阻止对象添加新属性时触发。
- isExtensible:当使用 Object.isExtensible() 检查对象是否可扩展时触发。
- ownKeys:当使用 Object.getOwnPropertyNames()、Object.getOwnPropertySymbols() 或 for...in 循环枚举对象的自身属性时触发。
- apply:当使用 Function.prototype.apply() 调用函数时触发。
- construct:当使用 new 运算符创建对象时触发。
ES6 Proxy 实例方法详解
get
get 方法在读取某个属性时触发。它接收三个参数:
- target:目标对象。
- property:要读取的属性名。
- receiver:调用 get 方法的代理对象。
get 方法可以返回任意值,包括原始值、对象、函数等。如果 get 方法返回 undefined,则会引发 TypeError 异常。
set
set 方法在写入某个属性时触发。它接收四个参数:
- target:目标对象。
- property:要写入的属性名。
- value:要写入的属性值。
- receiver:调用 set 方法的代理对象。
set 方法必须返回一个布尔值,表示写入操作是否成功。如果 set 方法返回 false,则会引发 TypeError 异常。
has
has 方法在使用 in 操作符检查属性是否存在时触发。它接收两个参数:
- target:目标对象。
- property:要检查的属性名。
has 方法必须返回一个布尔值,表示属性是否存在。如果 has 方法返回 false,则 in 操作符会返回 false。
deleteProperty
deleteProperty 方法在使用 delete 操作符删除属性时触发。它接收两个参数:
- target:目标对象。
- property:要删除的属性名。
deleteProperty 方法必须返回一个布尔值,表示删除操作是否成功。如果 deleteProperty 方法返回 false,则会引发 TypeError 异常。
getPrototypeOf
getPrototypeOf 方法在使用 Object.getPrototypeOf() 获取对象的原型时触发。它接收一个参数:
- target:目标对象。
getPrototypeOf 方法必须返回一个对象,表示对象的原型。如果 getPrototypeOf 方法返回 null,则会引发 TypeError 异常。
setPrototypeOf
setPrototypeOf 方法在使用 Object.setPrototypeOf() 设置对象的原型时触发。它接收两个参数:
- target:目标对象。
- prototype:要设置的原型对象。
setPrototypeOf 方法必须返回一个布尔值,表示设置操作是否成功。如果 setPrototypeOf 方法返回 false,则会引发 TypeError 异常。
preventExtensions
preventExtensions 方法在使用 Object.preventExtensions() 尝试阻止对象添加新属性时触发。它接收一个参数:
- target:目标对象。
preventExtensions 方法必须返回一个布尔值,表示阻止操作是否成功。如果 preventExtensions 方法返回 false,则会引发 TypeError 异常。
isExtensible
isExtensible 方法在使用 Object.isExtensible() 检查对象是否可扩展时触发。它接收一个参数:
- target:目标对象。
isExtensible 方法必须返回一个布尔值,表示对象是否可扩展。如果 isExtensible 方法返回 false,则对象不可扩展。
ownKeys
ownKeys 方法在使用 Object.getOwnPropertyNames()、Object.getOwnPropertySymbols() 或 for...in 循环枚举对象的自身属性时触发。它接收一个参数:
- target:目标对象。
ownKeys 方法必须返回一个数组,包含对象的所有自身属性名。
apply
apply 方法在使用 Function.prototype.apply() 调用函数时触发。它接收三个参数:
- target:目标函数。
- thisArg:函数的 this 值。
- args:函数的参数数组。
apply 方法必须返回一个值,表示函数的返回值。
construct
construct 方法在使用 new 运算符创建对象时触发。它接收三个参数:
- target:目标类。
- args:构造函数的参数数组。
- newTarget:new 运算符的目标函数。
construct 方法必须返回一个对象,表示创建的对象。
ES6 Proxy 实例方法示例
使用 get 方法拦截属性读取
const target = {
name: '张三',
age: 20
};
const proxy = new Proxy(target, {
get: function(target, property) {
console.log(`读取属性:${property}`);
return target[property];
}
});
console.log(proxy.name); // 读取属性:name
console.log(proxy.age); // 读取属性:age
使用 set 方法拦截属性写入
const target = {};
const proxy = new Proxy(target, {
set: function(target, property, value) {
console.log(`写入属性:${property},值为:${value}`);
target[property] = value;
}
});
proxy.name = '张三'; // 写入属性:name,值为:张三
proxy.age = 20; // 写入属性:age,值为:20
使用 has 方法拦截属性检查
const target = {
name: '张三'
};
const proxy = new Proxy(target, {
has: function(target, property) {
console.log(`检查属性:${property}`);
return target.hasOwnProperty(property);
}
});
console.log('name' in proxy); // 检查属性:name
console.log('age' in proxy); // 检查属性:age
使用 deleteProperty 方法拦截属性删除
const target = {
name: '张三'
};
const proxy = new Proxy(target, {
deleteProperty: function(target, property) {
console.log(`删除属性:${property}`);
delete target[property];
}
});
delete proxy.name; // 删除属性:name
使用 getPrototypeOf 方法拦截原型获取
const target = {
name: '张三'
};
const proxy = new Proxy(target, {
getPrototypeOf: function(target) {
console.log('获取原型');
return Object.getPrototypeOf(target);
}
});
console.log(Object.getPrototypeOf(proxy)); // 获取原型
使用 setPrototypeOf 方法拦截原型设置
const target = {};
const proxy = new Proxy(target, {
setPrototypeOf: function(target, prototype) {
console.log(`设置原型:${prototype}`);
Object.setPrototypeOf(target, prototype);
}
});
Object.setPrototypeOf(proxy, Array.prototype); // 设置原型:Array.prototype
使用 preventExtensions 方法拦截对象扩展
const target = {};
const proxy = new Proxy(target, {
preventExtensions: function(target) {
console.log('阻止对象扩展');
Object.preventExtensions(target);
}
});
Object.preventExtensions(proxy); // 阻止对象扩展
使用 isExtensible 方法检查对象是否可扩展
const target = {};
const proxy = new Proxy(target, {
isExtensible: function(target) {
console.log('检查对象是否可扩展');
return Object.isExtensible(target);
}
});
console.log(Object.isExtensible(proxy)); // 检查对象是否可扩展
使用 ownKeys 方法拦截属性枚举
const target = {
name: '张三',
age: 20
};
const proxy = new Proxy(target, {
ownKeys: function(target) {
console.log('枚举属性');
return Object.getOwnPropertyNames(target);
}
});
for (const property of Object.keys(proxy)) {
console.log(property); // 枚举属性
}
使用 apply 方法拦截函数调用
const target = function() {
console.log('函数调用');
};
const proxy = new Proxy(target, {
apply