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

ES6闭包与this绑定问题:为何dessert.scoops输出为0而非1?

为什么dessert.scoops输出0而不是预期的1?

先贴出你的代码(我补全了构造函数缺失的function关键字,否则会触发语法错误):

// constructor function
function IceCream() { this.scoops = 0; }

// adds scoop to ice cream
IceCream.prototype.addScoop = function() {
  const cone = this; // 保存当前this指向
  setTimeout(function() {
    cone.scoops++; // 修改scoops值
    console.log('scoop added!');
  }, 0.5);
};

const dessert = new IceCream();
dessert.addScoop();
console.log(dessert.scoops);

这个问题的核心是JavaScript事件循环的异步执行机制,简单来说就是:同步代码会优先执行完毕,异步任务要等同步代码全部跑完才会被处理。

具体到你的代码执行流程:

  • 调用dessert.addScoop()时,里面的setTimeout会被JS引擎放入宏任务队列——哪怕你设置的延迟只有0.5毫秒(提醒:setTimeout的第二个参数单位是毫秒,0.5实际是0.0005秒,而且浏览器有最小延迟限制,一般是4ms左右,实际等待时间会更长),这个回调函数不会立刻执行。
  • 紧接着的console.log(dessert.scoops)是同步代码,JS引擎会优先执行它——此时setTimeout的回调还没机会运行,cone.scoops++根本没执行,所以dessert.scoops还是初始值0,输出自然是0。
  • 等所有同步代码执行完毕,事件循环才会从宏任务队列里取出setTimeout的回调函数执行,这时候才会把scoops加1,同时打印scoop added!。

如果想让console.log(dessert.scoops)输出1,你需要把它放到异步上下文里,或者用Promise/async await来处理异步逻辑,举几个可行方案:

方案1:把日志放到setTimeout回调内

IceCream.prototype.addScoop = function() {
  const cone = this;
  setTimeout(function() {
    cone.scoops++;
    console.log('scoop added!');
    console.log(cone.scoops); // 这里会输出1
  }, 500); // 改成500毫秒更直观,能清晰看到先后顺序
};

const dessert = new IceCream();
dessert.addScoop();

方案2:用Promise+then处理异步

IceCream.prototype.addScoop = function() {
  const cone = this;
  return new Promise((resolve) => {
    setTimeout(function() {
      cone.scoops++;
      console.log('scoop added!');
      resolve();
    }, 500);
  });
};

const dessert = new IceCream();
dessert.addScoop().then(() => {
  console.log(dessert.scoops); // 这里输出1
});

方案3:用async/await简化异步流程

function IceCream() { this.scoops = 0; }

IceCream.prototype.addScoop = function() {
  const cone = this;
  return new Promise((resolve) => {
    setTimeout(() => {
      cone.scoops++;
      console.log('scoop added!');
      resolve();
    }, 500);
  });
};

async function getIceCreamScoops() {
  const dessert = new IceCream();
  await dessert.addScoop();
  console.log(dessert.scoops); // 输出1
}

getIceCreamScoops();

内容的提问来源于stack exchange,提问作者praveen-me

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:51:30