可能是你看过最完整的this指向总结!

前言

  • 前端的初学者在学习Javascript中this指向的时候经常都会一头雾水,尤其是在ES6箭头函数出现之前。

  • this指向之所以容易让人头疼,原因在于:this是在代码执行时根据环境和情况不同才决定绑定为什么值、

  • 所以本篇文章主要是介绍和总结了各种情况下的this指向,如果文中有写的不对的地方或者明显错误,还请不吝指出互相交流。如果对你有帮助,也请不要吝啬手中的点赞~谢谢

在开始之前,还是需要介绍this的一些基础知识,具体如下:

  1. this 是javascript中的一个关键字,并非是一个变量。
  2. this 关键字指向的是一个对象,而指向哪个对象,或者是这个对象的值是什么取决于使用(调用)的方式和。
  3. this 指向的值是可以通过手动方式去改变的,比如call、bind、apply方法。
  4. this 在严格模式和非严格模式下也会有差别。

一、全局普通函数

非严格模式下,全局普通函数的this指向 window

js 复制代码
 var a = 0; // 相当于window.a = 0
 function testWindow() {
        this.a = 1; //相当于window.a 
        console.log(this.a); //1
        console.log(window.a); // 1
        console.log(this); //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
      }
      testWindow();

严格模式下,普通函数的this执行undefined

js 复制代码
      var a = 1;
      function testStrict() {
        "use strict";
        console.log(this); //undefined
        console.log(this.a); // Uncaught TypeError: Cannot read property 'a' of undefined
      }
      testStrict();
      

二、对象的函数方法

javascript 复制代码
// 不管是严格模式还是非严格模式,this的指向都是调用这个函数的对象
 var a = 2;
      var obj = {
        a: 1,
        b: function () {
          console.log(this); //{a: 1, b: ƒ}
          console.log(this.a); //1
        }
      };
      obj.b();

做一个小练习题,将上面的代码进行一个简单的变化:

ini 复制代码
 var a = 2; 
      var obj = {
        a: 1,
        b: function () {
          console.log(this);  // indow {window: Window, self: Window,  ...}
          console.log(this.a); // 2
        }
      };
      
      var foo = obj.b;
      foo();   // 相当于window.foo()

为什么这个时候this是指向了window呢?

我们在开头说过,对象中函数调用,this是指向调用这个函数的对象。

foo变量接收了obj对象中的b函数,并且在全局作用域下执行,其实就相当于window.foo(),

那么自然就变成了第一种情况:全局作用域下普通函数调用指向window(非严格模式下)

三、构造函数

javascript 复制代码
//不管是严格模式还是非严格模式,构造函数中的this都是指向构造函数创建的对象实例

      function Test(a) {
        this.a = a;
        console.log(this.a); //1
      }

      Test.prototype.say = function () {
        console.log(this); //test {a: 1}
        console.log(this.a); //1
      };
      
      var t = new test(1);
      console.log(t); //test {a: 1}

      t.say();

四、事件处理函数

ini 复制代码
<body>
  <button id="btn">click</button>
  <button id="btn1">click1</button>
  <script>
    /**
     * this指向被绑定的目标对象
     * */
    var btn = document.getElementById("btn");
    btn.onclick = function () {
      console.log(this); // <button id="btn">click</button>
      this.innerHTML = "loading..";
      this.disabled = true;
    };


    var btn1 = document.getElementById("btn1");
    btn1.onclick = () => {
      console.log(this); //window
    };
  </script>
</body>

五、内联函数

以下代码包含了严格模式和非严格模式不同的情况。

xml 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
  
    <button onclick=" alert(this);">内联事件处理0</button> //元素本身即button

    <button onclick="alert((function(){'use strict'; return this})());">内联事件处理1</button> 
    
    //undefined

    <button onclick="alert((function(){ return this})());">内联事件处理2</button> 
    
    //window

    <button onclick="'use strict'; alert(this.tagName.toLowerCase());">内联事件处理3</button> 
    
    //button
    
  </body>
</html>

六、全局作用域

全局作用域下就比较简单了,直接记住就好。

xml 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      /**
       * 不管是严格模式还是不是严格模式this都指向window
       * */
      "use strict";
      console.log(this); // window
      
      
    
         
    </script>
  </body>
</html>

值得扩展的一点是,不同环境下的全局对象是不一样的

  1. 浏览器web: window,self,frames
  2. node环境下: global
  3. web worker : self

而在ES2020中,最终定义了 globalThis 作为在任何上下文中引用全局对象的标准方式。2020年初,所有现代浏览器和Node都实现了这个特性,具体详细可以参考:mdn web_docs

七、箭头函数

我们这里把箭头函数单独拿出来总结,在ES6中箭头函数的出现大大改善了this指向的'繁琐'情况:

  1. 箭头函数自身没有this;
  2. 箭头函数的this不是调用的时候决定的,而是在定义的时候所处的环境就已经决定了。
  3. 技巧: 箭头函数的this看外层是否有函数
  • 1).如果有,外层函数的this就是内部箭头函数的this
  • 2).如果没有,this就是window.

普通的箭头函数在全局环境下始终指向window

ini 复制代码
      let testES6 = () => {
        console.log(this); //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
      };
      
      testES6();

      let testES6Strict = () => {
        "use strict";
        console.log(this); //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
      };

      testES6Strict();

对象的箭头函数中,this则是指向执行该对象所处的执行上下文(执行环境)

kotlin 复制代码
 var obj = {
        fun: () => {
          console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
        }
      };
      
      obj.fun(); // fun箭头函数外层没有函数,指向window

      var obj = {
        fun: () => {
          "use strict";
          console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, ...}
        }
      };
      obj.fun();

事件处理中的箭头函数中,this指向window

xml 复制代码
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
</head>

<body>
  <button id="btn1">click1</button>
  <script>
    var btn1 = document.getElementById("btn1");
    btn1.onclick = () => {
      console.log(this); //window
    };
  </script>
</body>

</html>
相关推荐
于慨19 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz19 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶19 小时前
前端交互规范(Web 端)
前端
CHU72903519 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing20 小时前
Page-agent MCP结构
前端·人工智能
王霸天20 小时前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航20 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界20 小时前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript
PieroPc20 小时前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi
悟空瞎说20 小时前
深入 Vue3 响应式:为什么有的要加.value,有的不用?从设计到源码彻底讲透
前端·vue.js