深入解析JavaScript中this指向机制与常见误区

作者:小括号时间:2026-10-30 12:58:17浏览:159

本文深入探讨JavaScript中this的指向机制,指出其并非在定义时确定,而是在执行时由调用者决定。文章通过多个代码示例解析全局调用、对象方法调用、嵌套对象调用及赋值后调用等不同场景下的this行为,并详细讲解构造函数中new关键字对this的影响,以及return语句返回值类型对this最终指向的覆盖规则。

JavaScript this指向机制概述

首先需要明确的是,this的指向在函数定义阶段是无法确定的,只有在函数实际执行时才能判定this的具体指向。尽管网络上许多文章声称this最终指向调用它的对象,但这种理解并不完全准确,这也导致初学者在理解this时常常感到困惑。接下来将对此进行深入剖析。

学习this关键字的原因在于,若具备函数式编程或面向对象编程背景,会清楚其用途;若无相关基础,可暂略过此文,但作为JavaScript的核心概念,有兴趣的读者仍可参考。

基础调用场景下的this指向

示例1:


 function a(){
  var user = "小J";
  console.log(this.user); //undefined
  console.log(this); //Window
}
a(); 

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


function a(){
  var user = "小J";   
console.log(this.user); //undefined console.log(this);  
} 
window.a() //Window 

与前述代码类似,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,需参考后续几个示例。

复杂对象调用与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不指向window,此处暂不探讨严格模式,感兴趣者可自行查阅。

================================================>>>>> 

情况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仅指向其上一级对象,无论该对象是否包含所需属性。

赋值后调用与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直接执行fn不同。

关于JavaScript中this指向的探讨,其核心在于不同执行环境下的指向差异。前述总结虽存在细微偏差,但这源于环境变量的动态变化,需通过实践逐步体会。

构造函数中的this指向

构造函数版this:


function Fn(){
  this.user = "小J";
}
var a = new Fn();
console.log(a.user); //小J 

对象a之所以能访问函数Fn内的user,是因为new关键字改变了this指向,使其指向对象a。使用new即创建对象实例,可参考示例3,此处用变量a创建Fn的实例(相当于复制一份Fn到对象a中),仅创建未执行,调用者为对象a,故this指向对象a。Fn中为何有user?因使用new即等同于复制一份Fn到对象a中。

此外,还可自行改变this指向,即使用call、apply、bind方法。

this与return语句的交互

补充小问题:当this遇到return时。


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

再看一个示例。


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

再举一例。


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

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


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

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


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

严格模式与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。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章