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

JavaScript闭包中this关键字的行为问题咨询

为什么在Node.js中使用this.n的setTimeout回调会输出undefined?

你遇到的问题核心在于函数执行时this的指向差异,以及闭包的工作方式不同,咱们一步步拆解来看:

先看正常工作的g(i)函数

function g(i){ return function() { console.log(i); } }
for(i=0;i<4;i++) { setTimeout(g(i),3000); }

这里g(i)返回的是一个闭包函数,它直接捕获了外部函数g的参数i。每次循环调用g(i)时,都会创建一个全新的函数作用域,把当前循环的i值单独保存下来。3秒后每个回调执行时,都能拿到各自对应循环的i值,所以会输出0 1 2 3,这是闭包的典型正确用法。

再看出问题的f(i)函数

function f(i){ this.n = i; return function() { console.log(this.n); } }
for(i=0;i<4;i++) { setTimeout(f(i),3000); }

这里有两个关键的问题点:

  1. 调用f(i)时this的指向:
    你直接调用f(i)(没有用new关键字作为构造函数),在Node.js的非严格模式下,this会指向全局对象global;如果是严格模式,this会是undefined。不管哪种情况,this.n = i其实是在给全局对象赋值(如果是严格模式这里会直接报错),而且循环四次后,global.n会被最后一次的3覆盖。

  2. setTimeout回调执行时this的指向:
    在Node.js中,setTimeout的回调函数是在严格模式环境下运行的,此时this的默认指向是undefined。所以当回调函数function() { console.log(this.n); }执行时,this是undefined,访问undefined.n自然就得到undefined了。

如何修复f(i)函数?

如果你想让f(i)实现和g(i)一样的效果,可以试试下面几种方法:

  • 用变量保存当前this(闭包捕获):
    function f(i){ 
      this.n = i; 
      const self = this; // 保存当前作用域的this
      return function() { console.log(self.n); } 
    }
    
  • 用箭头函数继承外部this:
    箭头函数不会绑定自己的this,它会继承外部函数作用域的this:
    function f(i){ 
      this.n = i; 
      return () => { console.log(this.n); } 
    }
    
  • 用bind强制绑定this:
    通过bind方法把回调函数的this固定为f函数执行时的this:
    function f(i){ 
      this.n = i; 
      return function() { console.log(this.n); }.bind(this); 
    }
    

修改后,回调函数就能正确访问到对应的n值,输出预期的0 1 2 3了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:14:40