高级特性与API
约 897 字大约 3 分钟
2025-11-24
Proxy 能够监听对象中的对象的引用吗?
问题
Proxy 能够监听对象中的对象的引用吗?
不能直接监听。
Proxy 默认只代理对象的一层属性。如果对象的某个属性值本身是另一个对象(嵌套对象),那么对该嵌套对象 内部属性的读写操作,不会触发外层 Proxy 的拦截器(handler), 因为嵌套对象本身 不是 Proxy,而是原始引用。
示例:
const obj = {
a: { b: 1 },
};
const proxy = new Proxy(obj, {
get(target, key) {
console.log("get", key);
return target[key];
},
set(target, key, value) {
console.log("set", key, value);
target[key] = value;
},
});
proxy.a.b = 2; // 不会触发任何日志!原因:proxy.a 返回的是原始对象 { b: 1 },对它的 .b = 2 操作完全绕过了外层 Proxy。
如何监听嵌套对象?
必须对每个嵌套对象也创建 Proxy,即实现 深度代理:
function reactive(obj) {
if (obj === null || typeof obj !== "object") return obj;
Object.keys(obj).forEach((key) => {
obj[key] = reactive(obj[key]); // 递归代理
});
return new Proxy(obj, {
get(target, key) {
console.log("get", key);
return reactive(target[key]); // 返回也需代理
},
set(target, key, value) {
console.log("set", key, value);
target[key] = reactive(value); // 新值也需代理
return true;
},
});
}Vue 3 的 reactive() 就是基于这种深度 Proxy 实现的。Vue3 中的响应系统可阅读这里。
apply、call、bind
问题
apply、call、bind 的区别?
apply、call、、bind 都是用来改变函数执行上下文的,也就是函数运行时 this 的指向。
apply
apply 接收两个参数:function.apply(thisArg, [argsArray])。第一个参数是 this 的指向,第二个参数是函数接收的参数且以数组的形式传入。且第一个参数为 null 或 undefined 时 this 指向 window 。 apply 调用函数后会立即执行,且 this 指向只临时改变一次。
call
call 与 bind 很多相似之处:接收两个参数、调用函数后也会立即执行,且 this 指向只临时改变一次、当第一个参数为 null 或 undefined 时 this 指向 window 。它们的区别在于 call 传入的第二个参数是一个参数列表。
bind
bind 传入的参数与 call 一样,第一个为指定的 this ,第二个为 参数列表。区别在于它不是立即执行,而是返回一个永久改变 this 指向的函数,且第二个参数可以分多次传入(因为已经如同另一个函数)。
对比表
| apply | call | bind | |
|---|---|---|---|
| 参数 | thisArg, [argsArray] | thisArg, arg1, arg2, ... | thisArg, arg1, arg2, ... |
| 执行 | 立即执行 | 立即执行 | 返回一个改变 this 指向的函数 |
| this | 临时改变 | 临时改变 | 永久改变 |
| 参数列表 | 数组 | 参数列表 | 参数列表 |