setTimeout回调函数 this指向问题

本文主要介绍setTimeout的回调函数的this指向问题

例子1:回调函数是一个普通函数

setTimeout 的回调函数是一个普通函数,而不是箭头函数,因此它有自己的上下文,this 指向全局对象(在浏览器中是 window 对象)

js 复制代码
 var name = "我是全局的name";  // 注意这里的name必须用var声明,不可以是let,用let打印出来的就是undefined
 // 因为var可以让a是全局作用域,但是let不可以,所以访问对象不存在的属性返回undefined
    const obj = {
      name: "我是局部的name:John",
      greet: function () {
        setTimeout(function () {
          console.log("this", this); // window
          console.log(" this.name:" + this.name);
        }, 1000);
      },
    };

    obj.greet();


参考文章

例子2:回调函数是箭头函数

箭头函数的this继承自外部的greet()

js 复制代码
     var name = "我是全局的name";
    const obj = {
      name: "John",
      greet: function () {
        setTimeout(() => {
          // 因为是箭头函数,所以往上找,所以是greet的this,
          // 那么greet的this是什么呢? 谁调用它就是谁,所以是obj
          // 所以 这里的this是obj
          console.log("this", this); // obj
          console.log(" this.name:" + this.name); // 输出:Hello, John
        }, 1000);
      },
    };
    obj.greet();

例子3:回调函数是匿名函数

但是在匿名函数中,因为匿名函数的执行环境具有全局性,所以它的this一般指向window。

js 复制代码
  var name = "我是全局的name";
    const obj = {
      name: "John",
      greet: function () {
        setTimeout(function () {
          console.log("this", this);
          console.log(" this.name:" + this.name);
        }, 1000);
      },
    };
    obj.greet();

解决第一个例子中的this问题:使用bind

javascript 复制代码
const obj = {
  name: 'John',
  greet: function() {
    setTimeout(function() {
      console.log(this.name);
    }.bind(this), 1000);
  }
};

obj.greet(); // 输出:Hello, John

在这个例子中,.bind(this)this 绑定到了 setTimeout 内部的回调函数中,确保 this 在回调函数内部指向 obj 对象。

当然,也可以用例子2的箭头函数方法来解决

扩展案例

主要看 user.sleep();的this指向!!

js 复制代码
<script>
    console.log(this); // 此处为 window
    // 箭头函数
    const sayHi = function () {
      console.log("sayHi", this);
    };
    // 普通对象
    const user = {
      name: "小明",
      // 该箭头函数中的 this 为函数声明环境中 this 一致
      walk: () => {
        console.log("walk", this); // 箭头函数本身没有this,所以往上找,
        // user是对象,也没有this,所以继续向上找,所以最后是window
      },

      sleep: function () {
        let str = "hello";
        console.log("sleep的function", this); // obj
        let fn = () => {
          console.log(str);
          console.log("sleep里面的fn", this); // 该箭头函数中的 this 与 sleep 中的 this 一致
          // obj
        };
        // 调用箭头函数
        fn();
      },
    };

    // 动态添加方法
    user.sayHi = sayHi;

    // 函数调用
    user.sayHi();
    user.sleep();
    user.walk();
  </script>
相关推荐
千鼎数字孪生-可视化13 分钟前
Web技术栈重塑HMI开发:HTML5+WebGL的轻量化实践路径
前端·html5·webgl
凌辰揽月13 分钟前
7月10号总结 (1)
前端·css·css3
天天扭码36 分钟前
很全面的前端面试——CSS篇(上)
前端·css·面试
EndingCoder39 分钟前
搜索算法在前端的实践
前端·算法·性能优化·状态模式·搜索算法
sunbyte44 分钟前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleVerticalSlider(双垂直滑块)
前端·javascript·css·vue.js·vue
Favor_Yang1 小时前
SQL Server通过存储过程实现HTML页面生成
前端·信息可视化·sqlserver·存储过程
中微子2 小时前
JavaScript事件循环机制:面试官最爱问的10个问题详解
前端
Eighteen Z2 小时前
CSS揭秘:10.平行四边形
前端·css·css3
拾光拾趣录2 小时前
虚拟DOM
前端·vue.js·dom
爱学习的茄子2 小时前
JavaScript事件循环深度解析:理解异步执行的本质
前端·javascript·面试