深入解析JavaScript中this指向机制与常见误区
本文深入探讨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。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
