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

JavaScript不安全变量引用问题:如何修正循环中属性访问错误?

问题分析与解决方案

这问题我之前踩过坑!核心原因是箭头函数会捕获外层作用域的变量引用,而不是每次循环时的变量快照。你用var声明的key是函数级作用域的变量,整个循环里只有一个key的引用——循环结束后,key的值停在了最后一个属性名key2,所以不管你调用哪个get(),都会取到values[key2]的值,这就是为什么实际输出是val2。

下面给你几种可行的修改方案:

方案1:用let声明循环变量

let会在每次循环迭代时创建一个块级作用域的新变量,这样箭头函数捕获的就是当前迭代的那个key的独立引用:

var values = { "key1": "val1", "key2": "val2" };
const properties = {};
// 把var改成let,让每次循环都有独立的key变量
for (let key in values) {
  properties[key] = { get: () => values[key], set: (val) => { values[key] = val } };
}
console.log(properties["key1"].get()); // 输出val1,符合预期

方案2:用立即执行函数表达式(IIFE)隔离作用域

如果你的环境不能用ES6的let,可以用IIFE手动创建独立作用域,把当前循环的key值传进去保存:

var values = { "key1": "val1", "key2": "val2" };
const properties = {};
for (var key in values) {
  // 用IIFE捕获当前key的快照
  (function(currentKey) {
    properties[currentKey] = { 
      get: () => values[currentKey], 
      set: (val) => { values[currentKey] = val } 
    };
  })(key);
}
console.log(properties["key1"].get()); // 输出val1

方案3:用Object.entries()配合forEach迭代

forEach的回调函数会在每次迭代时接收独立的参数,天然隔离了作用域,写法也更简洁:

var values = { "key1": "val1", "key2": "val2" };
const properties = {};
// 解构出每个键值对的key
Object.entries(values).forEach(([key, _]) => {
  properties[key] = { 
    get: () => values[key], 
    set: (val) => { values[key] = val } 
  };
});
console.log(properties["key1"].get()); // 输出val1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 14:52:56