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>
相关推荐
猩兵哥哥2 分钟前
前端面向对象设计原则运用 - 策略模式
前端·javascript·vue.js
司宸3 分钟前
Prompt设计实战指南:三大模板与进阶技巧
前端
RoyLin5 分钟前
TypeScript设计模式:抽象工厂模式
前端·后端·typescript
华仔啊10 分钟前
Vue3+CSS 实现的 3D 卡片动画,让你的网页瞬间高大上
前端·css
江城开朗的豌豆19 分钟前
解密React虚拟DOM:我的高效渲染秘诀 🚀
前端·javascript·react.js
vivo互联网技术27 分钟前
拥抱新一代 Web 3D 引擎,Three.js 项目快速升级 Galacean 指南
前端·three.js
江城开朗的豌豆35 分钟前
React应用优化指南:让我的项目性能“起飞”✨
前端·javascript·react.js
会飞的青蛙40 分钟前
GIT 配置别名&脚本自动化执行
前端·git
再吃一根胡萝卜42 分钟前
🔍 当 `<a-menu>` 遇上 `<template>`:一个容易忽视的菜单渲染陷阱
前端