JavaScript中this指向详解与apply、call、bind用法对比

作者:小括号

时间:2026-10-23

浏览:492

本文深入解析JavaScript中this关键字的指向规则,涵盖直接调用、对象方法调用及DOM事件绑定等场景。重点对比call、apply和bind三种改变this指向的方法,通过具体代码示例说明其语法差异与执行特性,帮助开发者掌握函数上下文绑定的核心机制。

文章目录

本文详细解析JavaScript中this关键字的指向机制,通过具体示例展示其工作原理,为学习和工作提供实用参考。

在面试中,this指向问题以及apply、call和bind的区别是常见考点。本文将简明扼要地梳理this的指向规律。

this指向基本概念

基本概念

根据MDN官方文档,JavaScript中的this表现与其他语言不同,且严格模式与非严格模式存在差异。通常情况下,函数的调用方式决定了this的值。this在执行期间不可被赋值,且每次函数调用时this的值可能不同。

核心要点如下:

1. 指向this的对象被称为函数的上下文对象(context);

2. this的具体指向取决于函数被调用的方式。

无论函数调用形式如何复杂,只要抓住上述核心点,即可清晰判断this的指向。

基础调用场景测试

基础测试


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

当面试官询问this指向时,若函数未被调用,确实无法确定指向,因为“谁调用指向谁”是基本原则。

this指向基本概念

总结:通过函数名直接调用时,this指向全局对象window;通过对象.方法名调用时,this指向该对象。

DOM事件中的this指向

DOM对象调用函数时的this指向

1. 通过选择器获取元素并绑定事件属性时,this指向该DOM元素。示例如下:


document.getElementById('btn').onclick=function(){
  console.log('click'); //click
  console.log(this); //<button id="btn">button</button>
 }

2. 若在DOM标签中直接编写事件处理代码,this指向window。可通过将this作为参数传入方法中使用。示例如下:


html:
<button onclick="modify()">add</button>
<span id="count">0</span>
<button onclick="modify()">reduce</button>

script:
// 操作方法
 function modify(){
  console.log(this); //window
 }

此时因直接调用方法,this指向全局window对象。若需判断点击的是哪个按钮,可将this作为参数传入方法中。示例如下:


html:
<button onclick="modify(this)">add</button>
<span id="count">0</span>
<button onclick="modify(this)">reduce</button>

script:
// 操作方法
 function modify(_this){
  console.log(_this); 
// <button onclick="modify(this)">add</button>
// <button onclick="modify(this)">reduce</button>
 }

对象方法中的this动态绑定

对象中this的指向问题

先看一个简单示例:


var a=1;
function printA(){
 console.log(this.a);
}
var obj={
 a:2,
 foo:printA,
 bar:function(){
  printA();
 }
}
obj.foo(); //2
obj.bar(); //1var foo=obj.foo;foo(); //1

定义全局变量a及打印a的全局方法,随后定义对象obj,包含属性a及foo、bar两个方法。调用obj.foo()输出2,调用obj.bar()输出1。

分析:

无论printA在哪里定义,this的指向仅取决于被谁调用。在obj.foo()中,foo属性值为printA,由obj直接调用,故this指向obj,this.a即obj.a=2;

调用obj.bar()时,bar属性值为function(){printA()},未明确指定调用printA的对象,this默认指向全局对象window,故this.a=window.a=1;

第三种情况,将obj.foo赋值给变量foo,调用时相当于window.foo(),输出1。

总结:this的指向并非在函数声明时绑定,而是在函数运行过程中动态绑定。

改变this指向的方法对比

改变this指向的方法:apply、call、bind

通过示例说明,即便比喻可能不恰当,也能帮助理解其含义。


var liLei={
 name:'liLei',
 money:10,
 buyPen:function(){
  this.money=this.money-1;
  console.log(this.name+" have money:"+this.money)
 }
}

var hanMeiMei={
 name:'hanMeiMei',
 money:20,
 buyPan:function(){
  this.money=this.money-2;
  console.log(this.name+" have money:"+this.money)
 }
}

liLei.buyPen(); // liLei have money:9
hanMeiMei.buyPan(); //hanMeiMei have money:18

示例直观易懂,输出结果清晰可辨。假设韩梅梅欲购买笔具,因自身无此功能,便联系拥有该方法的李雷,委托其代为购买;同理,李雷欲购盘具时亦采用此方式。代码层面的实现逻辑如下:

JavaScript提供多种方法实现此功能:call、apply、bind。

call方法:

语法:call(thisObj,Object)

定义:调用一个对象的方法,以另一个对象替换当前对象。

说明:

call方法可用于替代另一个对象调用方法,将函数上下文从初始对象更改为thisObj指定的新对象。若未提供thisObj参数,则使用Global对象作为thisObj。


liLei.buyPen.call(hanMeiMei); //hanMeiMei have money:19
hanMeiMei.buyPan.call(liLei); //liLei have money:8

apply方法:

语法:apply(thisObj,[argArray])

定义:应用某一对象的方法,用另一个对象替换当前对象。

说明:

若argArray不是有效数组或arguments对象,将导致TypeError。若未提供argArray和thisObj任一参数,则使用Global对象作为thisObj,且无法传递任何参数。


liLei.buyPen.apply(hanMeiMei); //hanMeiMei have money:19
hanMeiMei.buyPan.apply(liLei); //liLei have money:8

bind方法:


liLei.buyPen.bind(hanMeiMei)(); //hanMeiMei have money:19
hanMeiMei.buyPan.apply(liLei)(); //liLei have money:8

总结:三种方法的共同点是均可改变this指向;不同点在于apply接受数组参数,call接受独立值参数;apply和call会直接调用方法,而bind仅改变this指向并返回新函数,不立即执行。

注:部分低版本浏览器不支持bind方法,进行浏览器兼容处理时需加以判断,具体实现此处略述。

以上为对this指向问题的个人理解,核心原则为“谁调用,指向谁”。JavaScript的世界充满奇妙之处,文中若有疏漏,欢迎指正。

本文内容希望对您的学习有所帮助,感谢支持。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章