本文深入解析JavaScript中this关键字的指向规则,通过对象方法、全局函数及回调函数等实例,阐明this在不同调用上下文中的变化。同时辨析按值传递与按引用传递的区别,解释对象参数在函数内部修改时的行为差异,帮助开发者准确掌握JS核心概念。
本文通过具体实例详细解析JavaScript中函数this关键字的使用方式,旨在为读者提供清晰的参考与学习材料。
this关键字与函数调用的基本关系
在JavaScript开发中,函数内部频繁使用this关键字。this是一个关键字,本质上是一个指针,它指向当前代码执行的环境作用域,通常也被称为上下文(context)。从概念上讲,函数是编程语言中用于重复调用的代码块。在JS中,当函数被赋值给对象的属性时,该函数被称为对象的方法。例如:
var m={};
m.title='title';
m.show=function(){
alert(this.title)
}
m.show()
上述代码展示了将函数作为对象m的方法来调用。在这种情况下,this关键字的指向明确为对象m。
如果直接通过函数名进行调用,则属于普通函数调用。例如:
var a=1212;
function show(){
alert(a)//1212
}
show()// 1212
在全局执行环境中,可以将全局变量视为window对象的属性,而全局函数则被视为window对象的方法。观察以下示例:
var m ={};
m.id='mmm';
m.show=function(){
alert(this.id);
}
var a={};
a.id='aaa';
a.show=m.show;
a.show(); //aaa
a.show=m.show; 先理解这句话,因为函数是个对象,
m.show=function(){
alert(this.id)
}
上述表达式表明,a.show与m.show同时引用指向同一个函数对象。
function(){
alert(this.id)
}
这实际上等同于:
a.show=function(){
alert(this.id)
}
因此,当调用a.show()时,this指向的是对象a。再来看另一个例子:
var m ={};
m.id='mmm'
m.show=function(){
alert(this.id)
}
var a={}
a.id='aaa'
a.show=function(){
m.show()
};
a.show(); //mmm
由此可见,调用a.show()实际上等同于执行m.show()方法,因此this指向的是对象m。
回调函数中的this指向问题
再看以下一个例子,初学者可能对此感到困惑:
var color='red';
var app = {};
app.color="green";
app.paint=function(node){
node.style.color=this.color;
alert(this.color);
}
function findNode(callback){
var btn =document.querySelector('.btn');
callback(btn);//传进来,
}
findNode(app.paint);
alert(this.color); //red 而不是green
在函数传参时,JavaScript采用按值传递(pass-by-value)的方式,而非按引用传递。
因此,当执行findNode(app.paint)时,传入的实际上是:
function(node){
node.style.color=this.color;
alert(this.color);
}
即函数引用的副本。由于findNode是在全局作用域中定义的,因此其中的this指向window(在非严格模式下)或undefined(在严格模式下)。
JavaScript参数传递机制:按值与按引用
关于传参机制,传递的是值的副本。
function show(a){
alert(a)
}
当参数为基本数据类型时,这一概念比较容易理解。
var b=10;
show(b)//alert(10);
而对于对象类型:
var c ={};
c.prop=true;
var showProp=function(obj){
obj.prop=false
}
showProp(c); //c.prop = false
有些人误以为上述示例是按引用传参。实际上,仍然是按值传递。当showProp(c)将c传入函数时,参数obj接收的是c的一个引用副本。在函数内部执行obj.prop=false,相当于修改了这个引用所指向的对象属性,因此外部c.prop也会变为false。
再看下面一个例子:
var c ={};
c.prop=true;
var showProp=function(obj){
obj = new Object();
obj.prop=false
return obj;
}
showProp(c);
alert(c.prop); //true
这里虽然修改了传入的obj,但如果按照所谓的“按引用传参”,外部对象的修改应该会反映出来。然而,示例中重新赋值obj为新对象,并未改变外部c的引用,因此外部c.prop仍为true。
希望本文的阐述能对大家的JavaScript程序设计有所帮助。