5分钟懂一个前端知识点系列之this关键字

前言

本人在学习this和原型(特别是this指向)的时候遇到了些许困惑,今天跟大家详细解释一下我在学习路上对this和原型的了解。难点先来攻克,今天先来讲讲this。这里统一声明不讨论严格模式下面的使用,因为我也不了解不能误导大家!

this

this 关键字在JavaScript中主要用于指代当前函数执行时的上下文对象,即函数内部的一个特殊变量,它指向函数调用时所属的对象。如果不太清楚函数上下文对象的可以看我的5分钟系列的其他文章,里面有讲解函数执行的上下文对象是个啥,存储的是什么内容,这里就不过多描述。

this 关键字是一个非常重要且有时可能引起混淆的概念。它的值取决于函数调用的上下文 ,即函数是如何被调用的,而不是函数在哪里被定义

普通函数this指向
  • 普通函数是不需要this对象的,因为仅仅只是使用函数并不需要知道函数执行的所属对象。所以一个普通函数是没有特定的this指向的,默认指向window全局对象
对象内部的this指向
  • 一个对象内部的this指向一般都是对象本身,当然也有例外
    看下面这段代码

    复制代码
      function Person(){
          function printThis(){
              console.log(this);
          }
      }
      var p1 =new Person().printThis;
      p1();

这里输出打印的this指向的是全局对象,因为这里的printThis函数是被当作一个普通函数调用了。普通函数调用this就是默认指向全局。

如何判断一个函数会被当成普通函数

如果一个函数不是作为某个对象的方法被调用,也没有使用.call(), .apply(), 或 .bind() 方法来改变this的绑定(这个可以暂时先不管),那么它被视为直接调用当作一个普通函数。

而上段代码创建了一个Person的实例,并尝试访问其printThis方法,但随后立即丢弃了新创建的实例,只保留了printThis函数的引用。当执行p1()时,printThis函数是以独立函数的形式被调用的,而非作为某个对象的方法调用。所以这里的printThis也被当做了普通函数。

如果回调函数是在全局上下文中定义的或者在非严格模式下被调用,且没有通过对象方法调用,那么this通常指向全局对象

箭头函数this指向

箭头函数不绑定自己的this,它会捕获其所在上下文的this值作为自己的this值,也就是词法作用域下的this

这意味着在箭头函数中,this的值是定义时所在的上下文决定的,而非调用时的上下文。这对于避免常规函数中常见的this混乱问题非常有帮助,尤其是在处理异步代码、回调函数或者在类的方法中。下面是一段实例代码

复制代码
const obj = {
    normalFunc: function() {
        setTimeout(function() {
            console.log(this); // 这里的this通常指向全局对象(非严格模式)
        }, 1000);
    },
    arrowFunc: function() {
        setTimeout(() => {
            console.log(this); // 这里的this指向obj对象,因为箭头函数没有自己的this,它继承了外层的this
        }, 1000);
    }
};

obj.normalFunc(); // 输出可能不是obj
obj.arrowFunc(); // 输出obj

测试

下面是有关的几道题目可以尝试做做。这里的答案都是在浏览器上执行,而非nodeJS因为两者全局对象有所不同。

1 复制代码
function showName() { console.log(this.name); }// 这里的this指向哪里?输出什么?
var name = "全局"; 
showName(); 

答案解析 : this指向全局对象(浏览器中是window,Node.js中是global)。

2 复制代码
const obj = {
  name: "Object",
  showName: function() {
    console.log(this.name);// 这里this指向什么?输出什么?
  }
};

obj.showName(); 

答案解析 : 当函数作为对象的一个方法被调用时,this指向该对象。因此,这里this指向obj

3 复制代码
function Person(name) {
  this.name = name;
  setTimeout(function() {
    console.log(this.name); // 这里this指向什么?输出什么?
  }, 1000);
}

const person = new Person("Alice"); 

答案解析 : 在setTimeout的回调函数中,如果没有特别处理,this通常会指向全局对象(非严格模式下),因为它是作为全局函数调用的。因此,这里的this.name可能不是预期的"Alice",而是全局对象的属性。但是,题目问的是new Person("Alice")中的this,这里this指向新创建的Person实例,即指向新创建的person对象。

4 复制代码
function Person(name) { this.name = name; } 
Person.prototype.printName = function() { console.log(this.name); }; // 这里的this指向哪里?
const person = new Person("Bob"); 
person.printName(); //输出什么?

答案解析 : 当通过实例调用原型链上的方法时,this指向该实例。因此,person.printName()中的this指向person实例,输出是"Bob"。

相关推荐
热爱编程的小曾6 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin18 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox31 分钟前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞2 小时前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行2 小时前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_593758102 小时前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox