本文详细解析JavaScript中this关键字的指向规则,涵盖全局window、当前调用对象及构造函数三种核心场景。通过具体代码示例,阐明this随执行上下文变化的机制,并结合new操作与call方法深入剖析构造函数中this的绑定原理,帮助开发者准确掌握this的使用逻辑。
JavaScript this指向的三种核心场景解析
本文通过具体实例深入解析JavaScript中this关键字的用法,旨在为读者提供清晰的参考与学习思路。
在早期学习JavaScript时,this的指向机制往往令人困惑,其逻辑与Java中的this存在显著差异。经过查阅大量资料并反复研读后,笔者梳理出核心要点,整理如下以防遗忘。
总体而言,JavaScript中this的指向主要归结为三种情况:指向全局window对象、指向当前调用对象,以及指向构造函数实例。
核心结论:在JavaScript中,this指向函数执行时的当前上下文对象。简而言之,哪个对象调用了该方法,this就指向哪个对象。
指向全局window对象
第一种情况:指向全局window对象
基础代码示例
var message = "this in window";
var printMessage = function(){
console.info(this === window);
console.info(this.message);
};
printMessage();
由于printMessage方法直接挂载在window对象上并被调用,因此输出结果为:
true this in window
接下来,我们将代码结构稍作复杂化处理。
var message = "this in window";
var printMessage = function(){
console.info(this === window);
console.info(this.message);
};
var obj = {
message: 'this in obj',
printMsg : function(){
printMessage();
}
};
obj.printMessage();
此时,printMessage方法仍属于window对象,故其this依然指向window。而obj.printMessage方法则属于obj对象,具体逻辑分析如下。
因此,输出结果依然显示为:true this in window
指向当前调用对象
第二种情况:指向当前调用对象
针对当前对象的情况,我们对代码进行微调。
var message = "this in window";
var printMessage = function(){
console.info(this === window);
console.info(this.message);
};
var obj = {
message: 'this in obj',
printMessage : window.printMessage
};
obj.printMessage();
运行结果:
false this in obj
正如预期,结论与前述一致:obj.printMessage方法属于obj对象,因此this指向obj。
进一步增加复杂度,观察以下代码逻辑。
var message = "this in window";
var printMessage = function(){
console.info(this === window);
console.info(this.message);
};
var obj = {
message: 'this in obj',
printMessage : function(){
var obj2 = {
message:'this in obj2',
printMessage: window.printMessage
};
obj2.printMessage();
}
};
obj.printMessage();
最终执行的是obj2.printMessage(),因此当代码执行到this时,该this指向obj2。
运行结果:
false,this in obj2
这验证了之前的观点:谁调用了方法,this就指向谁。
构造函数中的this
第三种情况:构造函数中的this
var Person = function(){
this.age = 1;
this.name = 'no name';
};
var p = new Person();
console.info('age = ' + p.age);
console.info('name = ' + p.name);
运行结果:
age = 1 name = no name。
构造函数对this进行了何种处理?前文《深入浅出理解javaScript原型链》中已对new操作符进行过分析。
var Person = function(){};
var p = new Person();
new操作的过程可拆解为以下三个步骤: (1) var p={}; 即初始化一个空对象p (2) p.__proto__ = Person.prototype; 将Person的原型赋值给p的原型 (3) Person.call(p); 即执行构造函数Person,并将p作为上下文进行初始化
call方法对this的影响
接下来重点讨论call方法的作用。
call方法详解
适用对象:Function 对象 功能:调用一个对象的方法,并以另一个对象替换当前上下文对象。
语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
参数说明: thisObj 可选。将被用作当前上下文对象的对象。 arg1, arg2, , argN 可选。将被传递的方法参数序列。
功能说明: call方法可用于替代另一个对象调用方法。该方法能将函数的上下文从初始环境切换为由thisObj指定的新对象。若未提供thisObj参数,则默认使用Global对象作为thisObj。
简而言之,call方法的核心作用是更改默认方法的this指向。调用call的对象必然是方法对象,执行时,该方法的this将指向call方法的第一个参数,逻辑十分直接。
var p = new Person();
当调用构造函数Person时,内部可能通过call机制处理,使Person内部的this指向p。此时,this.age = 1等效于p.age = 1,从而为对象p添加了age属性。
希望本文的阐述能对读者的JavaScript程序设计工作有所帮助。