JavaScript中this关键字的四种调用方式与箭头函数特性详解

作者:函数茶馆

时间:2026-10-22

浏览:663

本文深入解析JavaScript中this关键字的绑定规则。详细讲解对象方法调用、普通函数调用、构造函数调用以及apply/call调用四种方式下this的指向差异。特别针对内部函数this丢失问题,介绍保存this变量的传统解法,并重点阐述ES6箭头函数如何固定this指向定义时上下文,以及call/apply在箭头函数中失效的特性。

文章目录

JavaScript this关键字概述

本文通过具体实例详细解析JavaScript中this关键字的使用机制,旨在帮助读者深入理解并正确应用,供参考学习。

JavaScript中的this指向具有多样性,它可能指向全局对象、当前所在对象或任意指定对象,具体取决于函数的调用方式。主要包含以下几种调用场景:作为对象的方法调用、作为普通函数直接调用、作为构造函数调用,以及通过apply或call方法调用。

对象方法调用中的this指向

对象方法调用场景

当函数作为对象的方法被调用时,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 对象

需要特别强调的是,this的值是在函数执行时刻动态确定的,而非在函数定义时确定。即使是以对象方法的形式调用,如果将该方法以函数引用的形式传递到其他作用域中执行,this的指向也会随之改变。以下示例说明了这一机制:


var a = {
  aa : 0,
  bb : 0,
  fun : function(x,y){
    this.aa = this.aa + x;
    this.bb = this.bb + y;
  }
};
var aa = 1;
var b = {
  aa:0,
  bb:0,
  fun : function(){return this.aa;}
}
a.fun(3,2);
document.write(a.aa);//3,this指向对象本身
document.write(b.fun());//0,this指向对象本身
(function(aa){//注意传入的是函数,而不是函数执行的结果
  var c = aa();
  document.write(c);//1 , 由于fun在该处执行,导致this不再指向对象本身,而是这里的window
})(b.fun);

通过上述示例可以清晰看到this指向的变化,这是初学者容易混淆的关键点。

普通函数调用与内部函数this丢失问题

普通函数调用场景

当函数被直接调用(非对象方法形式)时,this关键字默认绑定到全局对象(在浏览器环境中通常为window)。


var x = 1;
function test(){
  this.x = 0;
}
test();
alert(x); //0

这种机制会导致潜在问题:在函数内部定义的内部函数,其this同样会指向全局对象,这往往与开发者的预期相悖。具体代码表现如下:


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

运行结果不仅未能实现预期的移动效果,反而意外生成了两个全局变量。解决这一问题的方法是,在进入内部函数之前,先将外层的this保存到一个变量中,然后在内部函数里使用该变量。修正后的代码如下:


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

构造函数调用中的this应用

构造函数调用场景

在JavaScript中,当使用new关键字创建构造函数实例时,可以利用this关键字指向新创建的对象。这种方式可以有效避免函数内部this指向全局对象的问题。


var x = 2;
function test(){
  this.x = 1;
}
var o = new test();
alert(x); //2

apply与call方法对this的控制

apply或call调用场景

apply和call方法的主要作用是改变函数执行时的上下文环境,即手动指定this绑定的对象。两者的功能相似,区别在于参数传递方式:apply要求参数以数组形式传入,而call要求参数逐个分开传入。此处以apply为例进行说明:


var name = "window";
var someone = {
  name: "Bob",
  showName: function(){
    alert(this.name);
  }
};
var other = {
  name: "Tom"
};
someone.showName();   //Bob
someone.showName.apply();  //window
someone.showName.apply(other);  //Tom

从结果可以看出,正常访问对象方法时,this指向该对象。使用apply且无参数时,this指向全局对象;使用apply并传入参数时,this则指向传入的那个参数对象。

ES6箭头函数的this固定机制

箭头函数调用场景

需要补充说明的是,在ES6标准引入的箭头函数中,this的指向始终绑定在函数定义时所处的上下文环境中,而不是函数执行时的环境。通过以下示例进行理解:


var o = {
  x : 1,
  func : function() { console.log(this.x) },
  test : function() {
    setTimeout(function() {
      this.func();
    }, 100);
  }
};
o.test(); // TypeError : this.func is not a function

上述代码执行报错,原因是this的指向从预期的对象o变为了全局对象。我们需要对代码进行如下修改:


var o = {
  x : 1,
  func : function() { console.log(this.x) },
  test : function() {
    var _this = this;
    setTimeout(function() {
      _this.func();
    }, 100);
  }
};
o.test();

通过预先在外部保存this变量即可解决。此时可以利用箭头函数的特性,如前所述,箭头函数的this始终指向定义时的上下文,而非执行时。因此,将上述代码修改为使用箭头函数的形式:


var o = {
  x : 1,
  func : function() { console.log(this.x) },
  test : function() {
    setTimeout(() => { this.func() }, 100);
  }
};
o.test();

修改后,this成功指向对象o。还需注意一点:箭头函数中的this指向是固定的,不会随调用方式改变。这意味着即使使用call或apply方法,也无法改变箭头函数中this的指向。


var x = 1,
  o = {
    x : 10,
    test : () => this.x
  };
o.test(); // 1
o.test.call(o); // 依然是1

通过上述分析,可以清晰理解各种调用情况下this绑定对象的区别。

希望本文的阐述能对JavaScript程序设计有所帮助。

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章