JS 的 this 是怎么工作的

引言:初期学习 JS 的时候,通常会对以下的问题存在疑惑

1:写 JS 时,this 为啥时而指向 window,时而指向当前对象?

2:箭头函数的 this 为啥 "不听话"?和普通函数到底差在哪?

3:call/apply/bind 改 this 指向,该怎么选才不踩坑?

一、this 是什么

首先,我们要明白一点,this 不是 "指向函数自身"

this 是函数执行时的 "上下文对象"

在实际应用时, this 具体代表的时谁,看的是 this 被谁调用

this 是一个代词,用在不同的地方代表不同的值

1.如果 this 被用在全局,在浏览器环境下,this 指向的其实是 window

js 复制代码
function fn() { console.log(this); }
fn(); // 浏览器环境下 this 指向 window

2.如果 this 在被函数调用时,涉及 this 的绑定规则

二、this的绑定规则

1. 默认绑定

当函数被独立调用时,函数中的 this 指向 window

例如

js 复制代码
function fn() { console.log(this); }
fn(); // 浏览器环境下 this 指向 window

又如

js 复制代码
var a = 1
function foo() {
  console.log(this.a); // 1
}

再如

js 复制代码
var a = 1
function foo() {
  console.log(this.a);
}
function bar () {
  var a = 2
  foo()
}
bar() //  浏览器为 1, node 为 undefined

注意:这里全局作用域下的 var a = 1 ,其实等效于 window.a , 而 Node.js 中模块内 var 声明的变量不挂载到 global

2.隐式绑定

当函数引用有上下文对象且被该对象调用时,函数中的 this 会绑定 到这个上下文对象上

例如

js 复制代码
const foo = {
  a: 1,
  bar: function() {
    console.log(this.a);
  }
}
foo.bar() // 1

只有这种写法,函数作为属性值被调用,才叫被函数调用

3.隐式丢失

当一个函数被多层对象调用时,函数的 this 指向最近的那个对象

例如

js 复制代码
function foo() {
  console.log(this.a);
}

var obj = {
  a: 1,
  foo: foo
}
var obj2 = {
  a: 2,
  foo: obj
}
obj2.foo.foo() // 1

有点像英语里的就近原则

4. 显示绑定

  • fn.call(obj,x,y) 显示的将 fn 里面的 this 绑定到 obj 这个对象上, call 负责帮 fn 接受参数
  • fn.apply(obj,[x,y])
  • fn.bind(obj,x,y)()

常见的就是这几种,相当于是强行掰弯 this 到别人身上

现在来介绍他们的写法

1.call

js 复制代码
// 带参数的函数
const fn = function(b, c) {
  console.log(this.a + b + c);
};

// 最简调用:this + 零散参数
fn.call({a: 2}, 3, 4); // 输出 9(2+3+4)

2.bind

返回的是一个函数,需要人为调用

js 复制代码
const fn1 = function(b, c) {
  console.log(this.a + b + c);
};

// 写法1:先绑定(this+预设参数),后传剩余参数
const boundFn = fn.bind({a: 2}, 3);
boundFn(4); // 输出 9(2+3+4)

// 写法2:极致简洁(绑定+调用一行完成)
fn1.bind({a: 2}, 3, 4)(); // 输出 9

3.apply

延迟执行,属于异步

apply 只传 "必须的"------ 绑定的 this + 一维数组参数,数组能字面量就不临时变量

js 复制代码
const fn2 = function(b, c) {
  console.log(this.a + b + c);
};

// 场景1:参数是现成数组(最简)
const params = [3, 4];
fn2.apply({a: 2}, params); // 输出 9(2+3+4)

// 场景2:参数是临时数组(字面量写法,一行完成)
fn2.apply({a: 2}, [3, 4]); // 输出 9

汇总而言就是:

  • call:参数逐个传递,调用后立即执行

  • apply:参数以数组传递,调用后立即执行(适配参数不确定场景)

  • bind:参数逐个传递,返回新函数(延迟执行,适配定时器 / 事件)

  • 一句话区分:call/apply 立即执行,bind 延迟执行;call 散传参数,apply 传数组

三、 new 绑定

就像前面文章

[JS 原型与原型链"为什么构造函数 new 出来的实例,都能用同一个方法?" 这背后就是 "原型 + 原型链" 的复用逻 - 掘金](https://juejin.cn/post/7605051978872045587 "https://juejin.cn/post/7605051978872045587")

所介绍的,详细讲述了 new 内部的 this 工作原理,简单来说就是

1.new 的原理会导致函数的 this 指向实例对象

2.当构造函数中存在 return ,并且 return 的是一个引用类型的数据,则 new 的返回失效

四、箭头函数的 this

简单来说,就两句话:

箭头函数中没有 this 这个概念,写在了箭头函数中的 this ,也是它外层那个非箭头函数的 this

箭头函数继承的外层 this 无法修改

相关推荐
木斯佳3 小时前
前端八股文面经大全:中科星图前端日常实习(2026-04-29)·面经深度解析
前端
heRs BART3 小时前
spring-boot-starter和spring-boot-starter-web的关联
前端
龙猫里的小梅啊3 小时前
CSS(七)CSS列表控制
前端·css
浩冉学编程3 小时前
微信小程序中基于java后端实现官方的文本内容安全识别msgSecCheck
java·前端·安全·微信小程序·小程序·微信公众平台·内容安全审核
李李李勃谦3 小时前
鸿蒙PC配色方案工具:取色、配色生成与 CSS 导出
前端·css·华为·harmonyos
threelab3 小时前
Three.js 咖啡杯烟雾效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
Jul1en_4 小时前
Claude 迁移 Codex 工作流迁移与更新
java·服务器·前端·后端·ai编程
Heo4 小时前
14_React 中的更新队列 updateQueue
前端·javascript·面试
前端 贾公子4 小时前
解决浏览器端 globalThis is not defined 报错
前端·javascript·vue.js
宁雨桥4 小时前
前端与AI结合实战分享
前端·人工智能