JavaScript中this关键字的四种调用方式详解

作者:青柠

时间:2026-10-30

浏览:222

本文深入解析JavaScript中this关键字的绑定规则。通过对象方法调用、普通函数调用、构造函数调用以及apply/call调用四种场景,详细阐述this指向全局对象、当前对象或新实例的机制。文章还探讨了内部函数this丢失的问题及that变量解决方案,并演示了如何利用apply和call切换执行上下文,帮助开发者准确掌握JavaScript的核心概念。

文章目录

JavaScript中this关键字的四种调用方式详解

在JavaScript中,this关键字并非仅存在于对象方法的上下文中。在全局函数调用以及其他多种不同的执行语境下,this同样存在并指代特定对象。其具体指向可以是全局对象、当前所属对象或任意指定对象,这完全取决于函数被调用的具体方式。JavaScript中函数的调用方式主要包含以下几种:作为对象的方法调用、作为普通函数直接调用、作为构造函数调用,以及使用apply或call方法进行调用。

作为对象方法调用

1. 作为对象方法调用

在JavaScript中,函数本质上也是对象。因此,函数可以作为对象的属性存在,此时该函数被称为该对象的方法。当以这种方式调用函数时,this关键字会被自然绑定到该方法所属的对象上。

代码如下:

  
var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
    } 
}; 
point.moveTo(1, 1)//this 绑定到当前对象,即 point 对象

作为普通函数调用

2. 作为函数调用

函数也可以被直接调用,此时this关键字绑定到全局对象。在浏览器环境中,window即为该全局对象。例如以下代码:当函数被调用时,this被绑定到全局对象,随后执行赋值语句,这相当于隐式地声明了一个全局变量。通常情况下,这并不是调用者所期望的结果。

代码如下:

  
function makeNoSense(x) {
this.x = x;
} 
makeNoSense(5);
x;// x 已经成为一个值为 5 的全局变量

对于内部函数,即声明在另一个函数体内的函数,这种绑定到全局对象的方式会引发另一个问题。我们仍以之前的point对象为例,这次希望在moveTo方法内部定义两个函数,分别用于平移x和y坐标。结果可能出乎意料:point对象并未移动,反而产生了两个名为x和y的全局变量。

代码如下:

var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
// 内部函数
var moveX = function(x) {
this.x = x;//this 绑定到了哪里?
   }; 
// 内部函数
var moveY = function(y) {
this.y = y;//this 绑定到了哪里?
   };
moveX(x); 
 moveY(y); 
 } 
}; 
point.moveTo(1, 1); 
point.x; //==>0 
point.y; //==>0 
x; //==>1 
y; //==>1

这被视为JavaScript设计上的一个缺陷。理想的设计应该是内部函数的this绑定到其外层函数所对应的对象上。为了规避这一设计缺陷,JavaScript程序员采用了一种变量替代的方法,这已成为约定俗成的做法。该变量通常被命名为that。

代码如下:

var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
var that = this;
// 内部函数
var moveX = function(x) {
that.x = x;
     }; 
// 内部函数
var moveY = function(y) {
that.y = y;
     } 
moveX(x);
moveY(y);
     } 
 }; 
point.moveTo(1, 1);
point.x; //==>1
point.y; //==>1

作为构造函数调用

作为构造函数调用

JavaScript支持面向对象式编程,但与主流面向对象语言不同,JavaScript没有类(class)的概念,而是采用基于原型(prototype)的继承方式。因此,JavaScript中的构造函数也显得特殊:如果不使用new关键字调用,它就和普通函数无异。作为另一项约定俗成的准则,构造函数名称以大写字母开头,旨在提醒调用者使用正确的方式调用。如果调用方式正确,this将绑定到新创建的对象上。

代码如下:

function Point(x, y){
this.x = x;
this.y = y;
} 

使用apply或call调用

使用 apply 或 call 调用

让我们再次重申,在JavaScript中函数也是对象,而对象拥有方法。apply和call正是函数对象的方法。这两个方法功能强大,允许切换函数执行的上下文环境(context),即改变this绑定的对象。许多JavaScript技巧及类库都利用了这一特性。请看以下具体示例:

代码如下:

function Point(x, y){
this.x = x;
this.y = y;
this.moveTo = function(x, y){
this.x = x;
this.y = y;
   } 
}
var p1 = new Point(0, 0); 
var p2 = {x: 0, y: 0}; 
p1.moveTo(1, 1); 
p1.moveTo.apply(p2, [10, 10]);

在上面的示例中,我们使用构造函数创建了一个对象p1,该对象同时拥有moveTo方法;同时使用对象字面量创建了另一个对象p2。我们可以看到,使用apply方法可以将p1的方法应用到p2上,此时this也被绑定到对象p2上。另一个方法call也具备相同的功能,不同之处在于最后的参数不是作为一个数组统一传入,而是分开传入。

代码如下:

function Foo(){
//1.this引用的构造函数是argument.callee引用的对象
//说明是通过new操作符执行的构造函数
if(this.constructor==arguments.callee){
alert('Object Created');
}
//2.this是window, 那么是全局调用
if(this==window){
alert('normal call');
}
else{//3.否则是作为其他对象的方法来调用
alert('called by '+ this.constructor);
}
}
Foo();//全局函数调用
Foo.call(new Object());//作为一个object对象的成员方法来调用
new Foo();//被new操作符调用,执行对象构造

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章