Proxy
和 defineProperty
都是 JavaScript 中用于拦截和自定义对象行为的工具,但它们在功能、使用场景和实现方式上有显著的区别。
defineProperty的用法
js
const obj = {};
Object.defineProperty(obj, 'name', {
get() {
console.log('读取属性: name');
return this._name;
},
set(value) {
console.log(`设置属性: name = ${value}`);
this._name = value;
}
});
obj.name = 'Alice';
console.log(obj.name);
这里定义了一个空对象obj,Object.defineProperty()可以用于数据劫持,所以这里劫持了obj的name属性,并给予它额外的能力(当他被赋予值时触发set,被读取值的时候触发get)
注意:当对象里的属性被劫持了的话,就无法通过log访问到了,要通过get方法
js
const obj = {
name: 'John',
};
Object.defineProperty(obj, 'name', {
get() {
console.log('读取属性: name');
return 'John';
},
set(value) {
console.log(`设置属性: name = ${value}`);
this._name = value;
}
});
console.log(obj.name);
还有一点数据劫持只能劫持第一层的属性,如果对象里套对象是不行的
js
const obj = {
name: 'John',
age:{
n:18
}
};
function hello() {
console.log('Hello');
}
Object.defineProperty(obj, 'name', {
get() {
hello();
return this._age;
},
set(value) {
hello();
this._age = value;
}
});
obj.age.n = 19;
console.log(obj.age);
并没有打印hello
proxy的用法
Proxy
是一个构造函数,用于创建一个代理对象。它可以拦截对象的多种操作。
Proxy 可以理解成,在目标对象之前架设一层"拦截",外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
js
const target = {
name: 'Alice',
age: 25
};
function hello() {
console.log('Hello');
}
const handler = {
get(target, prop) {
hello();
console.log(`读取属性: ${prop}`);
return target[prop];
},
set(target, prop, value) {
hello();
console.log(`设置属性: ${prop} = ${value}`);
target[prop] = value;
return true; // 表示设置成功
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // 读取属性: name → Alice
proxy.age = 30; // 设置属性: age = 30
和Object.defineProperty不同的是,proxy是代理整个对象而不是前者中对象里的某一个属性
代理行为有13种,可以去官网查看:es6.ruanyifeng.com/#docs/proxy