JavaScript this 指向详解

前言

在 JavaScript 中,this是一个非常高频、也非常容易让人混乱的知识点。

很多初学者会发现:同样是一个函数,在不同场景下调用this的值居然不一样。

比如:

  • 普通函数里的this

  • 对象方法里的this

  • 构造函数里的this

  • 箭头函数里的this

  • callapplybind改变this指向

本文就来系统讲清楚:JavaScript 中 this 到底指向谁。


一、this 是什么?

this不是在函数定义时决定的,而是在函数调用时决定的

也就是说:

谁调用这个函数,this 通常就指向谁。

先看一个简单例子:

javascript 复制代码
const obj = {
  name: 'Tom',
  say() {
    console.log(this.name);
  }
};

obj.say(); // Tom

这里say()是被obj调用的,所以this指向obj


二、普通函数中的 this

1)浏览器非严格模式下

scss 复制代码
function test() {
  console.log(this);
}

test();

在浏览器非严格模式下,普通函数直接调用时,

this指向window


2)严格模式下

javascript 复制代码
'use strict';

function test() {
  console.log(this);
}

test();

严格模式下,普通函数直接调用时,

thisundefined


三、对象方法中的 this

如果函数作为对象的方法调用,那么this指向这个对象。

javascript 复制代码
const obj = {
  name: 'Alice',
  say() {
    console.log(this.name);
  }
};

obj.say(); // Alice

注意,真正决定this的,不是函数写在哪,而是怎么调用

ini 复制代码
const obj = {
  name: 'Alice',
  say() {
    console.log(this.name);
  }
};

const fn = obj.say;
fn(); // 浏览器非严格模式下通常是 undefined 或 window.name

这里fn()已经不是通过obj调用了,所以this不再指向obj


四、构造函数中的 this

当函数通过new调用时,this指向新创建的实例对象。

ini 复制代码
function Person(name) {
  this.name = name;
}

const p = new Person('Tom');
console.log(p.name); // Tom

这里this指向p


五、箭头函数中的 this

箭头函数没有自己的this,它的this取决于外层作用域

ini 复制代码
const obj = {
  name: 'Tom',
  say: () => {
    console.log(this.name);
  }
};

obj.say();

这里箭头函数不会绑定obj,而是继承外层的this

如果在浏览器全局环境下,通常指向window


一个更容易理解的例子

ini 复制代码
const obj = {
  name: 'Tom',
  say() {
    const fn = () => {
      console.log(this.name);
    };
    fn();
  }
};

obj.say(); // Tom

这里箭头函数fn继承了say()this,也就是obj


六、事件中的 this

在 DOM 事件中,普通函数里的this一般指向触发事件的元素。

javascript 复制代码
button.onclick = function () {
  console.log(this); // button 元素
};

如果写成箭头函数:

ini 复制代码
button.onclick = () => {
  console.log(this);
};

那么这里的this不再指向按钮,而是继承外层作用域。


七、call、apply、bind 改变 this

JavaScript 提供了三种显式改变this的方法:

  • call
  • apply
  • bind
arduino 复制代码
function say() {
  console.log(this.name);
}

const obj = { name: 'Tom' };

say.call(obj);  // Tom
say.apply(obj); // Tom

bind 不会立即执行,而是返回一个新的函数:

ini 复制代码
const fn = say.bind(obj);
fn(); // Tom

八、this 指向总结

可以简单记住下面几条:

  1. 普通函数直接调用 :浏览器非严格模式下指向 window

  2. 对象方法调用:指向调用它的对象

  3. 构造函数调用:指向新实例

  4. 箭头函数 :没有自己的 this ,继承外层

  5. call/apply/bind :可以显式指定 this


九、总结

this的核心不是"函数定义在哪",而是:

函数是如何被调用的。

只要抓住这句话,再结合几种常见场景,this就不会再那么抽象了。

相关推荐
程序员库里1 小时前
AI协同写作应用-TipTap基础功能
前端·javascript·面试
程序员阿峰1 小时前
【JavaScript面试题-算法与数据结构】手写一个 LRU(最近最少使用)缓存类,支持 `get` 和 `put` 操作,要求时间复杂度 O(1)
前端·javascript·面试
im_AMBER1 小时前
AJAX vs Fetch API:Promise 与异步 JavaScript 怎么用?
前端·javascript·面试
用户9714171814271 小时前
JavaScript 作用域与作用域链详解
javascript
用户9714171814272 小时前
JavaScript call、apply、bind 详解
javascript
用户9714171814272 小时前
JavaScript 深拷贝与浅拷贝详解
javascript
Highcharts.js2 小时前
Highcharts React v4 迁移指南(上):核心变更解析与升级收益
前端·javascript·react.js·react·数据可视化·highcharts·v4迁移
菌菌的快乐生活2 小时前
在 WPS 中设置 “第一章”“第二章” 这类一级编号标题自动跳转至新页面
前端·javascript·wps
hh随便起个名2 小时前
useRef和useState对比
前端·javascript·react