You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何函数中的Object无法像参数一样被Proxy代理?技术求助

JavaScript Proxy 未生效的原因及解决方案

问题说明

我编写了一段JavaScript代码,预期通过Proxy代理对象obj,但实际运行时obj并未被代理。我原本认为函数参数是引用传递,能实现代理,但未成功。希望了解背后的原理、我的认知误区,同时想问:能否仅通过函数参数将对象赋值给Proxy变量?

代码示例

let obj = {
  foo: "123"
};

function test(fn, object) {
  object = new Proxy(object, {
    get(target, key) {
      console.log('get');
      return target[key];
    },
    set(target, key, value) {
      console.log('set');
      target[key] = value;
      return true;
    }
  });
  fn();
}

test(() => {
  obj.foo = "helloworld";
  console.log(obj.foo);
}, obj);

原理分析

JavaScript的参数传递规则是按值传递:

  • 对于基本类型,传递的是值的副本;
  • 对于对象类型,传递的是对象引用的副本。

在你的代码中,test函数的object参数是外部obj引用的一个副本。当你执行object = new Proxy(...)时,只是修改了这个局部变量object的指向,让它指向新创建的Proxy实例,但外部的obj仍然指向原来的原始对象,完全不受影响。所以后续操作obj.foo时,操作的是原始对象,不会触发Proxy的钩子。

认知误区

你误以为函数参数是“引用传递”——即修改参数会直接影响外部变量。但实际上,JS中不存在真正的引用传递:传递对象时,只是把对象的引用值复制了一份给参数,参数和外部变量是两个独立的引用,只是指向同一个对象。修改参数的指向(比如赋值新对象/Proxy)不会改变外部变量的指向,只有通过引用修改对象的内部属性时,才会影响到外部(因为两者指向同一个对象)。

补充问题解答:能否仅通过函数参数将对象赋值给Proxy变量?

不能。因为函数参数是局部变量,修改它的指向只会在函数内部生效,无法影响外部的变量。如果要让外部变量指向Proxy实例,有几种可行方案:

方案1:让函数返回Proxy实例,外部变量接收

let obj = {
  foo: "123"
};

function createProxy(object) {
  return new Proxy(object, {
    get(target, key) {
      console.log('get');
      return target[key];
    },
    set(target, key, value) {
      console.log('set');
      target[key] = value;
      return true;
    }
  });
}

// 外部变量接收代理对象
obj = createProxy(obj);
obj.foo = "helloworld"; // 触发set
console.log(obj.foo); // 触发get

方案2:在回调中使用代理后的对象

let obj = {
  foo: "123"
};

function test(fn, object) {
  const proxiedObj = new Proxy(object, {
    get(target, key) {
      console.log('get');
      return target[key];
    },
    set(target, key, value) {
      console.log('set');
      target[key] = value;
      return true;
    }
  });
  // 将代理对象传入回调
  fn(proxiedObj);
}

test((proxied) => {
  proxied.foo = "helloworld"; // 触发set
  console.log(proxied.foo); // 触发get
}, obj);

方案3:用包裹对象传递(不推荐,仅作演示)

把目标对象放在一个包裹对象里,传递包裹对象后修改其属性指向Proxy:

let wrapper = { obj: { foo: "123" } };

function test(fn, wrapper) {
  wrapper.obj = new Proxy(wrapper.obj, {
    get(target, key) {
      console.log('get');
      return target[key];
    },
    set(target, key, value) {
      console.log('set');
      target[key] = value;
      return true;
    }
  });
  fn();
}

test(() => {
  wrapper.obj.foo = "helloworld"; // 触发set
  console.log(wrapper.obj.foo); // 触发get
}, wrapper);

内容的提问来源于stack exchange,提问作者user469485

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 11:16:57