本文深入解析JavaScript中this关键字的8种典型用法,涵盖HTML内联事件、DOM绑定、DHTML赋值、类定义、原型扩展、CSS表达式及闭包场景。重点分析不同调用方式下this指向的差异,特别是IE attachEvent与标准DOM绑定的区别,以及函数内部this与外层作用域的关联机制,帮助开发者避免常见的引用错误。
JavaScript this关键字概述
尽管初学时可能感到困惑,但一旦掌握,this关键字的使用既便捷又指向明确。然而,与经典的面向对象语言相比,JavaScript中的this行为显得更为复杂和多变。
接下来,我们将探讨JavaScript中this关键字在不同场景下的具体表现及其潜在的混乱点。
1、在HTML元素事件属性中inline方式使用this关键字:
HTML内联事件中的this
<div onclick="
// 可以在里面使用this
">division element</div>
我们通常采用的方式是调用类似 javascript: EventHandler(this) 的形式。实际上,这里可以放置任何合法的JavaScript语句,甚至可以在其中定义一个类(尽管这会生成一个内部类)。其背后的原理是,脚本引擎会为该div元素实例生成一个匿名的成员方法,并将onclick属性指向该方法。
2、用DOM方式在事件处理函数中使用this关键字:
DOM方式绑定事件处理函数
<div id="elmtDiv">division element</div>
<script language="javascript">
var div = document.getElementById('elmtDiv');
div.attachEvent('onclick', EventHandler);
function EventHandler()
{
// 在此使用this
}
</script>
在这种情况下,EventHandler函数内部的this关键字指向的是IE浏览器的window对象。这是因为EventHandler只是一个普通函数,在调用attachEvent后,脚本引擎对其的调用与div对象本身没有直接关联。此外,你可以检查EventHandler的caller属性,其值为null。若需在此方法中获取div对象的引用,应使用 this.event.srcElement。
3、用DHTML方式在事件处理函数中使用this关键字:
DHTML方式赋值事件处理函数
<div id="elmtDiv">division element</div>
<script language="javascript">
var div = document.getElementById('elmtDiv');
div.onclick = function()
{
// 在此使用this
};
</script>
此时的this关键字指向的是div元素对象实例。通过DHTML方式直接将EventHandler赋值给div.onclick,相当于为div对象实例添加了一个成员方法。与第一种HTML内联方式的区别在于,DHTML方式下脚本解析引擎不会再生成额外的匿名方法。
4、类定义中使用this关键字:
类定义与原型中的this使用
function JSClass()
{
var myName = 'jsclass';
this.m_Name = 'JSClass';
}
JSClass.prototype.ToString = function()
{
alert(myName + ', ' + this.m_Name);
};
var jc = new JSClass();
jc.ToString();
这是在JavaScript中模拟类定义时对this的使用,其逻辑与其他面向对象语言非常相似。但需要注意的是,成员属性和方法必须使用this关键字来引用。运行上述代码会提示myName未定义,因为myName是局部变量而非实例属性。
5、为脚本引擎内部对象添加原形方法中的this关键字:
原型方法扩展中的this指向
Function.prototype.GetName = function()
{
var fnName = this.toString();
fnName = fnName.substr(0, fnName.indexOf('('));
fnName = fnName.replace(/^function/, '');
return fnName.replace(/(^\s+)|(\s+$)/g, '');
}
function foo()
alert(foo.GetName());
这里的this指代的是被添加原型方法的类的实例,这与第4点中的类定义情况相似,没有特别之处。
6、结合2&4,说一个比较迷惑的this关键字使用:
复杂场景下的this陷阱分析
function JSClass()
{
this.m_Text = 'division element';
this.m_Element = document.createElement('DIV');
this.m_Element.innerHTML = this.m_Text;
this.m_Element.attachEvent('onclick', this.ToString);
}
JSClass.prototype.Render = function()
{
document.body.appendChild(this.m_Element);
}
JSClass.prototype.ToString = function()
{
alert(this.m_Text);
};
var jc = new JSClass();
jc.Render();
jc.ToString();
简要说明结果:页面运行后显示“division element”,点击确认并再次点击文字“division element”时,将显示“undefined”。
7、CSS的expression表达式中使用this关键字:
CSS expression表达式中的this
<table width="100" height="100">
<tr>
<td>
<div style="width: expression(this.parentElement.width);
height: expression(this.parentElement.height);">
division element</div>
</td>
</tr>
</table>
这里的this可以视为与第1种情况类似,它同样指代div元素对象实例本身。
8、函数中的内部函数中使用this关键字:
函数内部函数与闭包作用域
function OuterFoo()
{
this.Name = 'Outer Name';
function InnerFoo()
{
var Name = 'Inner Name';
alert(Name + ', ' + this.Name);
}
return InnerFoo;
}
OuterFoo()();
运行结果显示为:“Inner Name, Outer Name”。根据第2点的讲解,结果似乎是“Inner Name, undefined”更为合理,但正确结果确实是前者。这是由JavaScript变量作用域机制决定的,详细了解推荐参考相关文档及回复。
原来JScript中的关键字'var'还是有文章的原来JScript中的关键字'var'还是有文章的