导读:本期聚焦于崔健创作的《JavaScript 中 this 关键字到底指向谁?一文搞懂四种绑定规则》,敬请观看详情。一段看似相同的函数被不同对象调用后结果完全不同,问题往往出在 this 的绑定上。JavaScript 的 this 不像 Java 或 C++ 那样指向声明时的类实例,而是取决于函数如何被调用。默认绑定、隐式绑定、显式绑定、new 绑定四种规则共同决定 this 的最终指向,优先级也容易被误解。本文从调用位置出发,结合箭头函数特殊行为,拆解全局函数、对象方法、回调、构造函数等常见场景,同时分析严格模式、定时器回调、事件处理函数中的差异,帮助读者建立可预测的 this 判断流程,避免死记硬背。读完这篇,你可以用同一条分析链路应对面试和实际调试。

JavaScript 中的 this 关键字常常让人困惑,因为它的值不是在函数定义时确定的,而是在函数被调用时根据调用方式动态绑定。换句话说,同一个函数在不同地方调用,内部的 this 可能完全不同。理解这种动态性是掌握 this 指向的第一步。

JavaScript 中 this 关键字到底指向谁?一文搞懂四种绑定规则

很多开发者从面向对象语言转到 JavaScript 时,会习惯性地认为 this 指向当前对象或类实例。这个直觉在对象方法调用时成立,但在全局函数、回调函数、定时器等场景中却会失效。要准确判断 this,关键不是看函数写在哪里,而是看函数如何被调用。

一、调用位置决定 this:先找到调用栈

JavaScript 函数执行的瞬间会形成一个调用位置,也就是函数在哪里被调用。分析 this 的第一步是找到这个调用位置,它通常不是函数声明的位置,而是函数名前面那个调用表达式所在的位置。

例如,同样一个函数 showName 被赋给 obj 对象后,通过 obj.showName() 调用时,调用位置就是 obj.showName;而直接 showName() 调用时,调用位置是全局。前者把 this 绑定到 obj,后者在非严格模式下绑定到全局对象。严格模式下直接调用则为 undefined,因为默认绑定不再回退到全局对象。

function showName() {
  console.log(this.name);
}

var name = '全局';

var obj = {
  name: '局部',
  showName: showName
};

showName(); // 全局
obj.showName(); // 局部

从代码输出可以看到,函数体完全一样,但调用方式不同导致 this 不同。理解调用位置后,再看四种绑定规则会更加清晰。

二、四种绑定规则:默认、隐式、显式与 new

默认绑定是最基础的规则,当函数直接调用且不属于任何对象时触发。在非严格模式下,独立函数调用中的 this 指向全局对象;在严格模式下则为 undefined。严格模式的影响还取决于函数体是否处于严格模式,如果调用位置在严格模式但函数体不在,仍然遵循非严格模式的默认绑定,需要特别留意。

隐式绑定发生在函数作为对象方法被调用时。此时函数调用位置前的对象就是 this。常见的错误是方法被赋值给变量后再调用,隐式绑定会丢失,this 退回到默认绑定。这种隐式丢失在回调传参中尤其常见,例如 setTimeout(obj.method, 100) 实际执行的是独立函数调用。

var user = {
  name: 'Bob',
  sayName: function() {
    console.log(this.name);
  }
};

var fn = user.sayName;
fn(); // 非严格模式下输出 undefined 或全局 name,而不是 Bob

显式绑定通过 call、apply 和 bind 方法直接指定 this。call 与 apply 立即执行函数,区别在于参数传递方式:call 逐个传参,apply 使用数组传参。bind 返回一个绑定了 this 的新函数,不会立即执行,适合用在回调场景中固定 this。

function introduce(city, country) {
  console.log(this.name + ' 来自 ' + city + ', ' + country);
}

var person = { name: 'Carol' };

introduce.call(person, '上海', '中国');
introduce.apply(person, ['北京', '中国']);

var boundIntroduce = introduce.bind(person, '广州');
boundIntroduce('中国'); // Carol 来自 广州, 中国

new 绑定则发生在使用 new 关键字调用构造函数时。此时 JavaScript 会创建一个新对象,并把构造函数内部的 this 指向这个新对象。除非构造函数显式返回一个对象,否则 new 调用最终返回的就是这个新对象。

function Product(title) {
  this.title = title;
}

var phone = new Product('手机');
console.log(phone.title); // 手机

四种规则的优先级从高到低依次为:new 绑定、显式绑定、隐式绑定、默认绑定。这意味着显式绑定可以覆盖隐式绑定,但无法覆盖 new 绑定;new 与显式绑定同时使用时,bind 传入的 this 会被 new 创建的新对象替代。

三、箭头函数:从外层作用域继承 this

箭头函数没有自己的 this,它的 this 在定义时从外层最近的普通函数或全局作用域中捕获。正因如此,箭头函数内部的 this 不会因为调用方式不同而改变,call、apply、bind 也无法修改它。这个特性让箭头函数非常适合用于回调,避免传统函数中 this 丢失的问题。

function Counter() {
  this.count = 0;
  setInterval(() => {
    this.count++;
    console.log(this.count);
  }, 1000);
}

new Counter();

相反,如果对象方法需要使用对象自身的属性,就不要用箭头函数定义方法,否则 this 会捕获外层作用域而非方法所属对象。例如在对象字面量中直接写箭头函数方法,this 可能指向全局对象或外层实例,导致读取属性失败。

var obj = {
  value: 10,
  getValue: () => {
    return this.value;
  }
};

console.log(obj.getValue()); // 非严格模式下通常不是 10

判断箭头函数的 this,只需看它定义时所在的词法作用域中 this 是什么。如果外层是普通函数,就跟着外层函数的 this 走;如果外层是全局,就遵循全局 this 规则。这一特点与普通函数的动态 this 形成鲜明对比。

四、常见陷阱与调试建议

回调函数是 this 丢失的重灾区。事件监听回调中,浏览器通常把 this 绑定到触发事件的元素;但如果在回调内部再定义普通函数,内层函数的 this 会丢失。解决办法是使用箭头函数、在外部保存 const self = this、或用 bind 显式绑定。

定时器回调同样如此。setTimeout 执行的回调默认是普通函数调用,this 在非严格模式下指向全局对象。使用箭头函数可以沿用外层 this,使用 bind 也能固定上下文。类字段中的箭头函数还可以直接作为事件监听器,既保留 this 指向,又避免在构造函数中手动绑定。

class Button {
  constructor() {
    this.label = '提交';
    document.querySelector('#btn').addEventListener('click', this.handleClick);
  }

  handleClick = () => {
    console.log(this.label);
  };
}

实际调试时,可以在函数内部打印 this,观察调用栈。若遇到不确定的 this,先找调用位置,再按优先级套用绑定规则。箭头函数则直接看外层作用域。通过这种方式建立统一的判断流程,比死记硬背各个 API 的行为更可靠。

JavaScript thisthis 指向绑定规则修改时间:2026-08-26 15:54:04

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。