高级特性与API
约 947 字大约 3 分钟
2025-11-24
Proxy 能够监听对象中的对象的引用吗?
问题
Proxy 能够监听对象中的对象的引用吗?
想一想,以下代码会输出什么?为什么?
JS code example
Proxy 默认只代理对象的一层属性。如果对象的某个属性值本身是另一个对象(嵌套对象),那么对该嵌套对象 内部属性的读写操作,不会触发外层 Proxy 的拦截器(handler), 因为嵌套对象本身 不是 Proxy,而是原始引用。因此以上代码的执行流程实际上为:
// 执行 proxy.a.b = 2 时:
// 步骤1: proxy.a → 触发 get('a'),返回 target[key] 即 obj.a
// 步骤2: (返回的 obj.a).b = 2 → 直接在原始对象上设置属性
// proxy.set 不会触发,因为操作对象是 obj.a 不是 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 | 临时改变 | 临时改变 | 永久改变 |
| 参数列表 | 数组 | 参数列表 | 参数列表 |