JavaScript中this关键字的四种调用规则详解

作者:代码拾荒

时间:2026-10-25

浏览:237

本文详细解析JavaScript中this关键字的四种核心调用规则:全局函数调用、对象方法调用、事件处理中的隐式绑定以及构造函数调用。通过对比不同场景下this指向的变化,结合jQuery示例与apply/call方法,帮助开发者避免常见的上下文错误,编写更健壮的代码。

文章目录

全局函数调用中的this指向

JavaScript函数调用规则一


(1)全局函数调用:


代码如下:

 
function makeArray( arg1, arg2 ){
return [this , arg1 , arg2 ];
} 

这是最常用的函数定义方式。熟悉JavaScript的人对其调用方式应不陌生。


调用代码如下:


makeArray('one', 'two');


// => [ window, 'one', 'two' ]


此种方式属于全局函数调用。


为何称之为全局函数?


因为它是全局对象window的一个方法,


我们可以通过以下方式验证:


alert( typeof window.methodThatDoesntExist );


// => undefined


alert( typeof window.makeArray);


// => function


因此,我们之前的调用方式与下述调用等价:


window.makeArray('one', 'two');


// => [ window, 'one', 'two' ]


对象方法调用与事件处理陷阱

JavaScript函数调用规则二


(1)对象方法调用:


代码如下:

 
//creating the object
var arrayMaker = {
someProperty: 'some value here',
make: makeArray
}; 
arrayMaker.make('one', 'two'); // => [ arrayMaker, 'one', 'two' ]
//或者采用以下调用方式:
arrayMaker['make']('one', 'two'); // => [ arrayMaker, 'one', 'two' ]

此处与前例的区别在于,this的值指向了对象本身。


或许你会质疑:原始函数定义未变,为何this会变化?


提出疑问是合理的。这涉及JavaScript中函数的传递机制,


在JavaScript中,函数是一种标准数据类型,


确切地说是一个对象。你可以传递或复制它们。


仿佛整个函数连同参数列表和函数体都被复制,


并赋值给arrayMaker中的属性make,这等同于如下定义arrayMaker:


代码如下:

 
var arrayMaker = {
someProperty: 'some value here',
make: function (arg1, arg2) {
return [ this, arg1, arg2 ];
} 
}; 

若未弄懂调用规则二,事件处理代码中常会出现各类bug。例如:


代码如下:

 
<input type="button" value="Button 1" id="btn1" />
<input type="button" value="Button 2" id="btn2" />
<input type="button" value="Button 3" id="btn3" onclick="buttonClicked();"/>
< script type="text/javascript">
function buttonClicked(){
var text = (this === window) ? 'window' : this.id;
alert( text );
} 
var button1 = document.getElementById('btn1');
var button2 = document.getElementById('btn2');
button1.onclick = buttonClicked;
button2.onclick = function(){
buttonClicked();
}; 
< /script>

点击第一个按钮将显示”btn1”,因为这是方法调用,this指向所属对象(按钮元素)。


点击第二个按钮将显示”window”,因为buttonClicked是被直接调用的(非obj.buttonClicked()形式),


这与第三个按钮将事件处理函数直接置于标签内的情况一致。因此,点击第三个按钮的结果与第二个相同。


故请大家注意:


代码如下:

 
button1.onclick = buttonClicked;
button2.onclick = function(){
buttonClicked();
}; 

两者的this指向存在差异。


使用jQuery和apply/call重置this上下文

JavaScript函数调用规则三


若使用jQuery库,则无需过多考虑,它会重写this的值以确保其包含当前事件源元素的引用。


代码如下:

 
//使用jQuery
$('#btn1').click( function() {
alert( this.id ); // jQuery ensures 'this' will be the button
}); 

那么jQuery是如何重载this的值呢?


答案是:call()和apply();


随着函数使用增多,你会发现所需的this可能不在相同的上下文中,这会导致通信困难。


在Javascript中函数也是对象,函数对象包含一些预定义的方法,其中两个便是apply()和call(),我们可以使用它们来对this进行上下文重置。


代码如下:

 
<input type="button" value="Button 1" id="btn1" />
<input type="button" value="Button 2" id="btn2" />
<input type="button" value="Button 3" id="btn3" onclick="buttonClicked();"/>
< script type="text/javascript">
function buttonClicked(){
var text = (this === window) ? 'window' : this.id;
alert( text );
} 
var button1 = document.getElementById('btn1');
var button2 = document.getElementById('btn2');
button1.onclick = buttonClicked;
button2.onclick = function(){
buttonClicked.call(this); // btn2
}; 
< /script>

构造函数调用与new运算符的重要性

JavaScript函数调用规则四


(1)构造器


此处不深入探讨JavaScript中类型的定义,但此刻需知JavaScript中没有类,


且任何自定义类型需要一个初始化函数。使用原型对象(作为初始化函数的一个属性)定义类型也是不错的选择,


让我们创建一个简单的类型


代码如下:

 
//声明一个构造器
function ArrayMaker(arg1, arg2) {
this.someProperty = 'whatever';
this.theArray = [ this, arg1, arg2 ];
} 
// 声明实例化方法
ArrayMaker.prototype = {
someMethod: function () {
alert( 'someMethod called');
}, 
getArray: function () {
return this.theArray;
} 
}; 
var am = new ArrayMaker( 'one', 'two' );
var other = new ArrayMaker( 'first', 'second' );
am.getArray();
// => [ am, 'one' , 'two' ]
other.getArray();
// => [ other, 'first', 'second' ]

一个非常重要且值得注意的点是函数调用前的new运算符。若无此运算符,函数将如同全局函数,且我们创建的那些属性都将是创建在全局对象上(window),而这并非你所愿。


另一点,由于构造器内无返回值,若忘记使用new运算符,将导致部分变量被赋值为undefined。


因此,构造器函数以大写字母开头是一个好习惯,这可作为提醒,让你在调用时不忘记前置new运算符。


这样,初始化函数内的代码与你其他语言中编写的初始化函数相似。this的值将是你即将创建的对象。


总结


我希望通过这些内容帮助你理解各种函数调用方式的不同,


使你的JavaScript代码远离bug。


知晓this的值是你避免bug的第一步。

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章