前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库this 绑定规则与优先级
JavaScript函数与作用域

JavaScript 中 this 的绑定规则有哪些?优先级如何?

普通函数的 this 由调用方式决定,和定义位置无关。四种规则按优先级排:new 最高,显式绑定(bind 以及 call 和 apply)其次,obj.fn() 隐式绑定再次,最后是默认绑定。箭头函数没有自己的 this,不参与这套规则。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#函数与作用域
先看核心答案读代码示例
理解线索

判断 `this` 的四步

  1. new创建新对象并绑定为 this,优先级最高
  2. 显式绑定通过 call 和 apply 一次性指定,或用 bind 永久绑定
  3. 隐式绑定obj.fn() 里点号左边的对象就是 this

判断 this 不看函数在哪里声明,看它被调用时前面是什么。箭头函数例外,它根本没有自己的 this。

核心回答

先记住这个答案

普通函数的 this 不看定义位置,只看调用方式。拿到一个函数调用,按四条规则从高到低排查:第一,是不是 new 调用,是的话 this 就是新创建的对象;第二,有没有用 call 或 apply 或 bind 显式指定,有就用传入的那个值;第三,调用时点号左边有没有对象,有就是那个对象;第四,前面都不是,走默认绑定,严格模式下是 undefined,非严格模式下是全局对象。箭头函数根本没有自己的 this,它用的是定义时外层作用域的 this。

  • 先看是不是 new,再看有没有显式绑定
  • 再看调用时点号左边有没有对象
  • 都不是就走默认绑定,严格模式是 undefined
  • 箭头函数沿定义位置的作用域链查找,不受调用方式影响

四种绑定用一段代码全部看清

同一个普通函数,换不同方式调用,this 就会不一样。

对比四种调用方式JavaScript
'use strict'
function show() { return this?.name ?? 'none' }
const first = { name: 'first', show }
const second = { name: 'second' }

console.log(first.show())
console.log(show.call(second))
const bound = show.bind(first)
console.log(bound.call(second))
console.log(show())
查看输出与解释
first
second
first
none

first.show() 是隐式绑定,点号左边是 first,所以 this 指向它。show.call(second) 是显式绑定,手动把 this 指定为 second。bound 是用 bind 固定了 this 为 first 的包装函数,后面再用 call 传 second 也改不了,因为 bind 创建的绑定是永久的。最后一行 show() 前面什么都没有,走默认绑定,严格模式下 this 是 undefined,undefined?.name 返回 undefined,最终打印 none。

new 调用为什么优先级最高

new 会创建一个全新的对象,然后把 this 指向它,让构造函数往里面挂属性。即使函数已经被 bind 过,new 也会忽略 bind 绑定的 this,改用新对象。

new 覆盖 bindJavaScript
function Person(name) { this.name = name }
const BoundPerson = Person.bind({ name: 'ignored' })
const p = new BoundPerson('actual')
console.log(p.name)
查看输出与解释
actual

BoundPerson 已经用 bind 把 this 绑到了 { name: 'ignored' },但 new 调用时创建了新对象并让 this 指向它,所以 p.name 是 'actual'。不过 bind 预设的参数仍然有效,new 只覆盖 this,不影响参数。 这个优先级在实际项目里很少直接用到,但面试经常问,考的是你对 new 内部机制的理解。

隐式绑定最容易丢

隐式绑定的问题是它依赖调用时的写法。只要把方法从对象上取下来单独调用,this 就丢了。

比如 const fn = obj.show 之后再 fn(),这时候 fn 前面没有对象,走默认绑定,this 变成 undefined(严格模式)或全局对象。事件回调和 setTimeout 里传方法引用时最容易踩这个坑。

解决办法有三种:用 bind 固定 this,用箭头函数包一层(箭头函数会捕获外层的 this),或者在 class 里用箭头函数作为类字段属性。React class 组件时代经常看到构造函数里写 this.handleClick = this.handleClick.bind(this),就是在解决这个问题。

非严格模式的陷阱

非严格模式下,默认绑定的 this 不是 undefined 而是全局对象(浏览器里是 window,Node.js 里是 global)。更隐蔽的是,call(null) 和 call(undefined) 也会被替换成全局对象,call(42) 会被装箱成 Number 对象。

现代代码基本都是严格模式。ES 模块天然严格,class 内部也天然严格。面试时最好主动说明自己是在严格模式下分析的,避免因为模式不同导致答案和面试官预期不一致。

回答前,多想一步

容易答错的地方

以为 this 看定义位置
普通函数的 this 和它写在哪里没有关系。同一个函数可以挂到多个对象上,每次调用的 this 都可能不同。只有箭头函数才是看定义位置。
把箭头函数放进四条规则里讨论
箭头函数没有自己的 this,call 和 bind 以及 new 对它都无效。它用的是定义时外层作用域的 this,这个值在定义那一刻就固定了,后续怎么调用都不会变。面试时应该明确说「箭头函数不参与这套规则」。
试着用自己的话回答

面试官还会怎么问?

new 和 bind 同时出现,谁赢?

new 赢。new 创建新对象并绑定为 this,bind 预设的 this 被忽略。但 bind 预设的参数仍然生效,它们会排在 new 调用时传入的参数前面。

(0, obj.fn)() 的 this 是什么?

逗号表达式只保留最后一个值,也就是函数引用本身,点号左边的对象信息丢失了。这时候相当于普通调用,走默认绑定,严格模式下 this 是 undefined。Webpack 打包 CommonJS 模块时经常生成这种写法来避免模块函数里的 this 指向 exports。

回调函数里的 this 为什么经常丢?

把 obj.fn 作为回调传出去,实际执行时调用者是 setTimeout 或事件系统,不会用 obj.fn() 这种写法来调,隐式绑定就丢了。解决方案是用 bind 固定、箭头函数包裹,或者在 class 里用箭头函数作为类字段。

从一道题,走向一组知识

把知识连起来

函数与作用域

bind 和 call、apply 有什么区别?bind 返回的函数有什么特点?

这篇展开讲 bind 和 call 以及 apply 三者的区别,是显式绑定那条规则的细节补充。

函数与作用域

new 一个函数时,内部到底做了哪几步?this 指向谁?

深入讲 new 调用的内部步骤,解释为什么 new 的优先级比 bind 还高。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • this

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 四种绑定用一段代码全部看清
  3. new 调用为什么优先级最高
  4. 隐式绑定最容易丢
  5. 非严格模式的陷阱
  6. 容易答错的地方
  7. 面试官还会怎么问
  8. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑