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

如何为从其他对象动态添加的属性正确定义Getter/Setter?

问题分析与解决方案:Getter/Setter 闭包陷阱

你遇到的是JavaScript里循环闭包的变量捕获问题,这也是很多开发者刚接触闭包时容易踩的经典坑。

问题根源

你的代码中,for循环里用var声明的key是函数级作用域变量——整个循环过程中只有这一个key存在。当循环结束时,key的值会停留在最后一个遍历到的属性名(也就是name)。而你定义的getter和setter函数都是闭包,它们共享这个key变量,所以所有属性的读写操作最终都会指向values['name'],这就导致了设置Master.id=234后,读取Master.id返回的却是New master。

两种可行的修复方案

方案1:用立即执行函数(IIFE)创建独立作用域

通过IIFE把每次循环的key值封装到独立作用域里,让每个getter/setter都引用自己作用域内的变量:

var params = { id: 123, name: 'Old master' };
var Master = new function() {
  var values = {};
  for(var key in params) {
    // 用IIFE捕获当前循环的key值,绑定到currentKey上
    (function(currentKey) {
      Object.defineProperty(this, currentKey, {
        enumerable: true,
        set: function(value) { values[currentKey] = value; },
        get: function() { return values[currentKey]; }
      });
    }).call(this, key);
  }
  return this;
}()
Master.id = 234;
Master.name = 'New master';
console.log(Master.id); // 输出 234
console.log(Master.name); // 输出 New master

方案2:用ES6的let声明块级作用域变量

如果你的环境支持ES6,直接用let声明key就可以解决问题。let会在每次循环时创建一个全新的变量实例,每个getter/setter都会捕获当前循环的key:

var params = { id: 123, name: 'Old master' };
var Master = new function() {
  var values = {};
  // let声明的key是块级作用域,每次循环都有独立的变量
  for(let key in params) {
    Object.defineProperty(this, key, {
      enumerable: true,
      set: function(value) { values[key] = value; },
      get: function() { return values[key]; }
    });
  }
  return this;
}()
Master.id = 234;
Master.name = 'New master';
console.log(Master.id); // 输出 234
console.log(Master.name); // 输出 New master

可行性说明

完全可行!这是JavaScript中处理循环闭包的标准场景,只要解决了变量共享的问题,就能为每个属性绑定独立的getter/setter,实现对values中对应项的正确读写。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:01:52