js中如何改变this指向

1.this指向

什么是this指向?

在 JavaScript中,this的指向取决于函数被调用的方式,而非定义的位置

1.1常见的this

  1. 独立函数
    函数独立调用时,this指向全局对象(浏览器中为 window,Node.js中为global)。
javascript 复制代码
function show() {
  console.log(this); // window(非严格模式)
}
show();

严格模式下为undefined

javascript 复制代码
function show() {
  "use strict"
  console.log(this); // undefined
}
show(); // 如果window.show()那么此时的this指向的就是window
  1. 对象函数
    函数作为对象方法调用时,this 指向调用它的对象
javascript 复制代码
const user = {
  name: "Alice",
  greet() {
    console.log(`Hello, ${this.name}!`); // Hello, Alice!
  }
};
user.greet();

方法被分离后调用会导致this丢失

javascript 复制代码
const func = user.greet;
func(); // ❌ 错误:this 丢失(指向 window/undefined)
  1. 箭头函数
    箭头函数的this定义:箭头函数的this是在定义函数时绑定的,不是在执行过程中绑定的。简单的说,函数在定义时,this就继承了定义函数的对象。
    箭头函数内的this就是箭头函数外的那个this为什么?
    注意:箭头函数没有自己的this
javascript 复制代码
const obj = {
  name: "Dave",
  regularFunc: function() {
      console.log(this.name); // Dave(隐式绑定)
  },
  arrowFunc: () => {
      console.log(this.name); // 空(继承外层 this)window上没有name
  }
};
obj.regularFunc();
obj.arrowFunc();
javascript 复制代码
let name = "123";
let person = {
  name: "456",
  fn1: function() {
      // 这边的this和下面的setTimeout函数下的this相等
      let that = this;
      setTimeout(() => {
          console.log(this.name, that === this); // '456' true
      }, 0);
  },
  fn2: function() {
      // 这边的this和下面的setTimeout函数下的this不相等
      let that = this;
      setTimeout(function() {
          console.log(this.name, that === this); // '123' false
      }, 0);
  },
};
person.fn1(); // '456' true
person.fn2(); // '123' false
  1. DOM节点
    非严格模式
html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>最编程 创未来</title>
  </head>
  <body>
    <button>变色</button>
    <script>
      let elements = document.getElementsByTagName("button")[0];
      elements.addEventListener(
        "click",
        function () {
          this.style.backgroundColor = "#A5D9F3";
        },
        false
      );
    </script>
  </body>
</html>

严格模式

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>最编程 创未来</title>
  </head>
  <body>
    <button>变色</button>
    <script>
      'use strict'
      var elements = document.getElementsByTagName("button")[0];
      elements.addEventListener(
        "click",
        function () {
          console.log(this)
          this.style.backgroundColor = "#A5D9F3";
        },
        false
      );
    </script>
  </body>
</html>
  1. 内联事件函数

当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素,不区分严格或非严格模式

javascript 复制代码
<button onclick="console.log(this)">点击测试</button> <!-- <button onclick="console.log(this)">点击测试</button> -->

当代码被包括在函数内部执行时,其this指向等同于函数直接调用的情况,即在非严格模式指向全局对象window

javascript 复制代码
<button onclick="(function() { console.log(this) })()">点击测试</button> <!-- Window {window: Window, self: Window, document: document, name: '最编程', location: Location, ...} -->

当代码被包括在函数内部执行时,其this指向等同于函数直接调用的情况,在严格模式指向undefined

javascript 复制代码
<button onclick="(function() {'use strict'; console.log(this) })()">点击测试</button> <!-- undefined -->
  1. 构造函数
    构造函数中,this 指向新创建的实例对象Person{}
javascript 复制代码
function Person(name) {
  this.name = name;
}
const charlie = new Person("金小子");
console.log(charlie.name); // 金小子
javascript 复制代码
// 伪代码展示 new 的操作流程
const charlie = new Person("金小子");

// 实际发生的步骤:
// 1. 创建新对象
const tempObj = {};

// 2. 设置原型链
tempObj.__proto__ = Person.prototype;

// 3. 将 this 绑定到新对象并执行构造函数
Person.call(tempObj, "金小子"); // 此时构造函数内的 this = tempObj

// 4. 返回新对象
const charlie = tempObj;

以上就是常见的this指向,那么接下来来看改变this指向的方式。

2. call、apply、bind

JavaScript 的 call、apply 和 bind 都是用于显式绑定函数执行时的 this 指向。

三者核心区别:

● call:立即执行函数,逐个传递参数

● apply:立即执行函数,数组形式传递参数

● bind:不立即执行,返回新函数(永久绑定 this 和部分参数)

2.1 call

call

语法

javascript 复制代码
func.call(thisArg, arg1, arg2, ...)  

例子

javascript 复制代码
function greet(message) {
  console.log(`${message}, ${this.name}!`);
}

const person = { name: "Alice" };

// 将 greet 的 this 指向 person,并传递参数  
greet.call(person, "Hello"); // 输出: "Hello, Alice!"

● greet 中的 this 原本指向全局(如 window),但通过 call 将 this 绑定到 person 对象

● "Hello" 作为参数逐个传递

2.2 apply

语法

javascript 复制代码
func.apply(thisArg, [argsArray])  

示例

javascript 复制代码
function introduce(age, job) {
  console.log(`${this.name} is ${age} years old and works as a ${job}.`);
}

const person = { name: "Bob" };

// 将 introduce 的 this 指向 person,参数通过数组传递  
introduce.apply(person, [30, "developer"]); // 输出: "Bob is 30 years old and works as a developer."

● 参数以数组 [30, "developer"] 形式传递(适合动态参数场景)

● 等同于 introduce.call(person, 30, "developer")

2.3 bind

语法

javascript 复制代码
const newFunc = func.bind(thisArg, arg1, arg2, ...)  
newFunc()

示例

javascript 复制代码
function logHobby(hobby1, hobby2) {
  console.log(`${this.name} likes ${hobby1} and ${hobby2}.`);
}

const person = { name: "Charlie" };

// 创建新函数,永久绑定 this 和部分参数  
const boundFunc = logHobby.bind(person, "hiking");

// 调用新函数时只需传入剩余参数  
boundFunc("reading"); // 输出: "Charlie likes hiking and reading."

● bind 返回一个新函数 boundFunc,其 this 永久绑定为 person

● "hiking" 被预设为第一个参数,调用时只需传递剩余参数

总结

方法 执行时机 参数形式 是否返回新函数
call 立即执行 逐个参数 (arg1, arg2)
apply 立即执行 数组 ([args])
bind 延迟执行 逐个参数(可部分预设)

🌟 核心总结

this 指向是 JavaScript 中核心且易混淆的知识点,其本质遵循「调用决定指向」的原则(箭头函数除外):

普通函数:this 指向调用它的对象,独立调用时指向全局(严格模式为 undefined);

箭头函数:无自有 this,继承定义时外层作用域的 this;

构造函数 / 事件处理:this 分别指向实例对象、触发事件的 DOM 元素;

显式绑定:call/apply/bind 可强制修改 this 指向,三者仅在「执行时机、参数形式」上有差异(call/apply 立即执行,bind 返回新函数)。

📌 实践建议

日常开发中,优先通过「对象方法调用」「箭头函数」「bind 绑定」明确 this 指向,避免全局 this 污染;

处理动态参数时用 apply,需预设参数 / 延迟执行时用 bind,简单传参优先 call;

严格模式下需格外注意独立函数的 this 指向(变为 undefined),避免意外报错。

🎯 记忆口诀

this 指向:「谁调用,指向谁;箭头函数,找外层;构造 /new,指实例;显式绑定,听 call/apply/bind」;

绑定三兄弟:「call 逐个传,apply 数组传,bind 绑完等调用」。

相关推荐
门思科技2 小时前
基于 LoRaWAN 的 CJ/T 188 M-Bus 热量表采集方案解析:KC22 与 Edge-Bus 的工程化实践
前端·edge
捻tua馔...2 小时前
面试被问到-redux-toolkit用法
前端
qq_463408422 小时前
React Native跨平台技术在开源鸿蒙中使用内置的`fetch` API或者第三方库如`axHarmony`来处理网络通信HTTP请求
javascript·算法·react native·react.js·http·开源·harmonyos
cnnews2 小时前
用OpenCV实现烟花动画
开发语言·python·opencv·pygame·cv2
Rabi'2 小时前
Windows系统 Qt 整合 OpenCV4.12.0
开发语言·windows·qt·opencv
88号技师2 小时前
2025年10月一区SCI-中心碰撞优化算法Centered Collision Optimizer-附Matlab免费代码
开发语言·算法·数学建模·matlab·优化算法
zore_c2 小时前
【数据结构】堆——超详解!!!(包含堆的实现)
c语言·开发语言·数据结构·经验分享·笔记·算法·链表
leo_2322 小时前
从开发语言角度来谈谈SMP(中)--SMP(软件制作平台)语言基础知识之十三
开发语言·开发工具·smp(软件制作平台)·应用系统
IT_陈寒2 小时前
SpringBoot 3.0实战:5个高频踩坑点及性能优化方案,让你的应用吞吐量提升40%
前端·人工智能·后端