本文详细解析 JavaScript 中 this 关键字在运行时确定的四种核心场景:全局作用域、普通函数、构造函数及对象方法。重点探讨嵌套函数中 this 指向 window 的常见陷阱及其通过变量保存 this 的解决方案,并演示如何利用 call 和 apply 手动指定 this 指向,帮助开发者掌握 JS 核心机制。
JavaScript this 指向规则概述
this 的值是在程序运行时动态确定的。
JavaScript 中的 this 具体指向哪个对象,取决于代码执行时的上下文环境,主要可分为以下几种情况。
全局作用域中的 this
1. 全局作用域中的 this
在全局执行上下文中,this 默认指向 window 对象。
console.log(this);//指向window对象
this.x = 5//在全局作用域内创建一个x
//与this.x = 5的等价情况:
//var x = 5;
//x = 5;
在全局作用域中执行 var x=5,实际上等同于为 window 对象创建一个属性 x,并将其赋值为 5。
如果在定义变量时省略 var 关键字,JavaScript 引擎会将其视为全局变量,并自动将其作为 window 对象的属性进行处理。
函数中的 this:构造函数与普通函数
2. 函数中的 this
JavaScript 中的函数主要分为两类:直接调用的普通函数,以及通过 new 关键字创建对象实例的构造函数。
2.1 构造函数中的 this
在构造函数内部,this 指向当前正在创建的新对象,例如:
function Person(name){
this.name = name;//this指向该函数创建的对象person
}
var person = new Person("chaimm");
2.2 普通函数中的 this
普通函数被直接调用时,其内部的 this 指向 window 对象。如果上述例子中的 Person 函数被直接执行(而非通过 new 调用),其中的 this 将代表 window 对象,因此该函数执行后会在全局作用域中创建一个名为 name 的全局变量。
function Person(name){
this.name = name;//this指向window
}
Person("chai");//当作普通函数执行,this指向window对象
对象方法中的 this 及嵌套函数陷阱
3. 对象中的 this
在对象的方法中,this 指向调用该方法的当前对象,例如:
var person = {
name : "chaimm",
getName : function(){
return this.name;
}
}
在上述代码中,this 指向函数 getName 所属的对象实例。
然而,如果一个对象的方法内部嵌套定义了另一个函数,这个内部函数的 this 将指向 window 对象,而非外层对象。
var person = {
name : "chaimm",
setName : function(name){
(function(name){
this.name = name; //此时this并不代表person对象,而是代表window对象
})(name);
}
}
上述示例中,person 对象包含一个 getName 方法,而该方法内部又定义了一个匿名函数。这个内部函数的 this 指向 window 对象,而不是 person 对象。这通常被视为 JavaScript 设计中的一个特性(或 bug)。一般采取以下处理方式规避此问题:
var person = {
name : "chaimm",
setName : function(name){
var thar = this;//将this赋给that
(function(name){
that.name = name;//此时that指向person对象
})(name);
}
}
我们可以在 person 对象的第一层函数中,将 this 赋值给一个局部变量(如 that),然后在第二层嵌套函数中使用该变量。此时,that 指向 person 对象,从而可以正常访问 person 的属性。
注意:如果将对象中的方法赋值给一个变量,再通过该变量调用此方法,此时方法内部的 this 将指向 window 对象,而非原对象,如下所示:
var person = {
name : "chaimm",
getName : function(){
return this.name;
}
}
//将getName函数赋给一个新的变量
var newGetName = person.getName;
//通过新的变量调用这个函数,这个函数中的this将指向window
newGetName();//若全局作用域中没有name,则将返回undefined
使用 call 和 apply 手动指定 this
4. 使用 call 和 apply 函数改变 this 指向
这两个方法允许开发者手动指定被调用函数内部的 this 指向哪个对象。
//定义一个构造函数
var Person = function(name){
this.name = "";
this.setName = function(name){
this.name = name;
}
}
//创建两个对象
var personA = new Person("A");
var personB = new Person("B");
//使用personA的setName函数去修改personB的name属性
personA.setName.apply(personB,["C"]);
apply 用法
语法格式为:对象A.函数名.apply(对象B, 参数列表)。当对象B作为 apply 的第一个参数传入时,对象A的函数中的 this 将指向对象B。此时,对象A的该函数对 this 的操作将作用在对象B上,从而实现了用对象A的方法去操作对象B的属性。
以上是对 JavaScript this 关键字相关内容的整理,后续将继续补充相关资料,感谢大家的支持!