JavaScript中this指向详解与apply、call、bind用法对比
本文深入解析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指向全局对象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的世界充满奇妙之处,文中若有疏漏,欢迎指正。
本文内容希望对您的学习有所帮助,感谢支持。
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
