深入解析JavaScript中this指针的指向规则

作者:异步漫步

时间:2026-10-30

浏览:367

本文深入探讨JavaScript中this指针的指向机制。通过多个代码示例,解析全局函数、对象方法、构造函数以及返回值对this的影响。明确this在定义时不确定,仅在执行时由调用者决定。涵盖非严格模式下的默认指向、new关键字的作用及return语句的例外情况,帮助开发者准确理解this行为。

文章目录

JavaScript中this指针的指向规则

深入解析JavaScript中this指针的指向规则

首先需要明确的是,this的指向在函数定义阶段是无法确定的,只有在函数实际执行时才能确定this的具体指向。从本质上看,this最终指向的是调用该函数的对象(注:这一表述存在局限性,下文将解释其原因。尽管网络上多数文章持此观点,且在许多场景下适用,但这种理解并不完全准确,这也是导致this概念难以捉摸的原因)。接下来将对这一机制进行深入探讨。

学习this指针的意义在于:若你熟悉函数式编程或面向对象编程,便知其重要性;若未接触过,可暂略过本文,但若有兴趣,建议阅读,因为掌握this是JavaScript开发的核心基础。

全局与对象调用下的this指向

示例1:


function a(){
  var user = "追梦子";
  console.log(this.user); //undefined
  console.log(this); //Window
}
a();

根据前述观点,this最终指向调用它的对象。在示例1中,函数a实际上是被Window对象调用的,以下代码可验证这一点。


function a(){
  var user = "追梦子";
  console.log(this.user); //undefined
  console.log(this);  //Window
}
window.a();

上述代码逻辑相同。实际上,alert也是window对象的一个属性,同样由window对象调用。

示例2:


var o = {
  user:"追梦子",
  fn:function(){
    console.log(this.user); //追梦子
  }
}
o.fn();

此处的this指向对象o,因为函数fn是通过o.fn()执行的,因此指向对象o。再次强调,this的指向在函数创建时无法确定,仅在调用时确定,且指向调用者。务必厘清这一概念。

示例1和示例2的表述并不严谨,以下示例可推翻上述理论。

要彻底理解this,需参考后续几个示例。

示例3:


var o = { user:"追梦子", 
fn:function()
{ console.log(this.user); //追梦子 } } 
window.o.fn();

这段代码与前述代码相似,但此处this并未指向window。若按前述理论,this应指向调用它的对象。此处补充说明:window是JavaScript的全局对象,我们创建的变量实际上是window的属性,因此可通过window访问对象o。

暂不解释为何此例中this未指向window,继续观察以下代码。


var o = {
  a:10,
  b:{
    a:12,
    fn:function(){
      console.log(this.a); //12
    }
  }
}
o.b.fn();

此处同样由对象o调用,但this并未指向它。这是否意味着前文所述有误?并非如此,仅是前文表述不够严谨。接下来补充关键说明,即可彻底理解this的指向问题。

this指向的三种基本情况

情况1:若函数中存在this,且未被上一级对象调用,则this指向window。需注意,在JavaScript严格模式下,this指向undefined。本文暂不讨论严格模式,感兴趣者可自行查阅相关资料。

情况2:若函数中存在this,且被上一级对象调用,则this指向该上一级对象。

情况3:若函数中存在this,且该函数包含多个对象,即使由最外层对象调用,this仍指向其上一级对象。示例3可证明此点。若不信,请继续观察后续示例。


var o = {
  a:10,
  b:{
    // a:12,
    fn:function(){
      console.log(this.a); //undefined
    }
  }
}
o.b.fn();

尽管对象b中无属性a,this仍指向对象b,因为this仅指向其上一级对象,无论该对象是否包含所需属性。

函数赋值与最后调用者的关系

还有一种特殊情况,见示例4:


var o = {
  a:10,
  b:{
    a:12,
    fn:function(){
      console.log(this.a); //undefined
      console.log(this); //window
    }
  }
}
var j = o.b.fn;
j();

此处this指向window,是否令人困惑?原因在于未理解关键语句,该语句至关重要。

this永远指向最后调用它的对象,即执行时的调用者。示例4中,虽然函数fn被对象b引用,但在将fn赋值给变量j时并未执行,因此最终指向window。这与示例3不同,示例3直接执行了fn。

this的指向虽复杂,但本质一致,仅在不同场景下表现不同。前文总结存在细微偏差,并非错误,而是环境不同导致结果不同,需逐步体会。

构造函数中的this指向

构造函数版this:


function Fn(){
  this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子

此处对象a之所以能访问函数Fn内部的user,关键在于new关键字改变了this的指向,使其指向对象a。之所以判定a为对象,是因为new关键字用于创建对象实例。结合示例3理解,变量a创建了Fn的一个实例,这相当于将Fn函数复制了一份到对象a中。此过程仅完成创建而未执行,由于调用Fn的是对象a,故this自然指向a。Fn中为何存在user,是因为通过new关键字已将Fn复制至对象a中。

除上述情况外,还可手动改变this指向,详见《JavaScript中call,apply,bind方法的总结》一文,详细说明了手动更改this指向的方法。

构造函数中return语句对this的影响

更新一个小问题:当this遇到return时


function fn() 
{ 
  this.user = '追梦子'; 
  return {}; 
}
var a = new fn; 
console.log(a.user); //undefined

再看一个示例


function fn() 
{ 
  this.user = '追梦子'; 
  return function(){};
}
var a = new fn; 
console.log(a.user); //undefined

再来一个示例


function fn() 
{ 
  this.user = '追梦子'; 
  return 1;
}
var a = new fn; 
console.log(a.user); //追梦子
function fn() 
{ 
  this.user = '追梦子'; 
  return undefined;
}
var a = new fn; 
console.log(a.user); //追梦子

何意?

若返回值为对象,则this指向该返回对象;若返回值非对象,则this仍指向函数实例。


function fn() 
{ 
  this.user = '追梦子'; 
  return undefined;
}
var a = new fn; 
console.log(a); //fn {user: "追梦子"}

此外,尽管null也是对象,但此处this仍指向函数实例,因null具有特殊性。


function fn() 
{ 
  this.user = '追梦子'; 
  return null;
}
var a = new fn; 
console.log(a.user); //追梦子

严格模式与new操作符的补充说明

知识点补充:

1. 在严格模式下,默认this不再是window,而是undefined。

2. new操作符会改变函数this的指向。前文已提及,但未深入讨论,网上也较少涉及,故在此补充说明。


function fn(){
  this.num = 1;
}
var a = new fn();
console.log(a.num); //1

为何this指向a?首先,new关键字创建一个空对象,随后自动调用apply方法,将this指向该空对象,从而替代函数内部的this。

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章