html5中文学习网

您的位置: 首页 > 网站及特效实例 > javascript特效 » 正文

深入理解Javascript中this的作用域_javascript技巧_

[ ] 已经帮助:人解决问题

大家在使用Javascript的时候经常被this这个家伙搞得晕头转向的。对大多数有OOP开发经验的开发人员来说this是当前作用域中引用普通元素的标识符,但是在Javascript中它却显得古灵精怪的,因为它不是固定不变的,而是随着它的执行环境的改变而改变。在Javascript中this总是指向调用它所在方法的对象。PaGHTML5中文学习网 - HTML5先行者学习网

举一个简单的例子:PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
function test(){PaGHTML5中文学习网 - HTML5先行者学习网
alert(this);PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
var obj=function(){PaGHTML5中文学习网 - HTML5先行者学习网
var name='testObj';PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
obj.objTest=test;PaGHTML5中文学习网 - HTML5先行者学习网
test();PaGHTML5中文学习网 - HTML5先行者学习网
obj.objTest();PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

把这段代码放到HTML中运行这个页面,你会看到首先提示一个警告[object window],然后第二个警告。PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
var obj=function(){PaGHTML5中文学习网 - HTML5先行者学习网
var name='testObj';PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

我们先定义了一个test()方法,并在方法内部调用alert()方法将this显示出来,然后定义了一个obj函数对象,并给它加了一个私有的字段name,同时给它加了一个静态的方法objTest(),而这个函数则直接指向test()函数。PaGHTML5中文学习网 - HTML5先行者学习网

分别调用test()和obj.objTest()方法,第一次警告框提示的是Window对象,而第二次提示的是我们定义的obj这个函数的代码。这说明了test函数在两次执行的时候this的值是不同的!PaGHTML5中文学习网 - HTML5先行者学习网

这就说明了当调用函数的对象不同的时候,其内部的this关键字指代的对象是不同的。这里需要值得注意的是Javascript是基于对象的语言,当我们的变量或者函数定义在<script></script>标签的根下的时候其实相当于给window对象加了相应的属性或方法,所以当我们利用function test(){}代码定义一个函数的时候,其实相当于给window对象添加了一个新的函数,即window.test()函数。PaGHTML5中文学习网 - HTML5先行者学习网

我们可以做一个实验:PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
function test(){PaGHTML5中文学习网 - HTML5先行者学习网
alert(this);PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
alert(test===window.test);PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

警告框提示的将是true,这说明当我们在调用test()这个函数时相当于调用的是window.test()。所以当我们调用test()函数的时候调用这个函数的对象其实是window对象,this指代的是window对象,所以我们在alert(this)的时候弹出的警告窗口内容是[object Window]。我们将obj.objTest=test相当于把obj.objTest()指向test(),所以当我们调用obj.objTest()函数时相当于在obj调用了test()这个函数,所以现在this指代的是obj对象,提示的就是obj这个Function也就是我们看到的代码。PaGHTML5中文学习网 - HTML5先行者学习网

说到这应该也解释的差不多了,可能上面的例子太抽象,想象不出来它能在什么情况下用到,那我们现在就假设一个需求,做一个贴近实用一点的例子。PaGHTML5中文学习网 - HTML5先行者学习网

假设我们现在页面中的所有超链接在点击之后颜色要改为红色,用Javascript实现。大体的思路应该是获取页面中所有的<a>标签,然后遍历所有的<a>标签,给每一个注册一个click事件,事件触发后我们将它的color值设为red。PaGHTML5中文学习网 - HTML5先行者学习网

示例代码如下:PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
//改变颜色PaGHTML5中文学习网 - HTML5先行者学习网
function changeColor(){PaGHTML5中文学习网 - HTML5先行者学习网
this.style.color='#f00';PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
//初始化,给所有 a 标签注册事件PaGHTML5中文学习网 - HTML5先行者学习网
function init(){PaGHTML5中文学习网 - HTML5先行者学习网
var customLinks=document.getElementsByTagName('a');PaGHTML5中文学习网 - HTML5先行者学习网
for(i in customLinks){PaGHTML5中文学习网 - HTML5先行者学习网
//你也可以使用事件侦听器方式来注册事件PaGHTML5中文学习网 - HTML5先行者学习网
//由于要兼容IE,FF等浏览器可能需要更多代码,您可以自行编写PaGHTML5中文学习网 - HTML5先行者学习网
customLinks[i].onclick=changeColor;PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
window.onload=init;PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

将这段代码添加到HTML文档中,并在文档中添加一些超链接,当超链接点击后颜色会变成红色,这里我们定义的changeColor()函数中this关键字在点击超链接触发函数的时候它指代的是当前这个超链接。而如果你直接调用changeColor()函数浏览器会报错,提示Error: ‘this.style' is null or not an object或者undefined之类的错误。PaGHTML5中文学习网 - HTML5先行者学习网

不知道说到这能不能让正在看文章的你对Javascript中的this关键字有了一些自己的了解呢?或者你已经不耐烦了?(:P)PaGHTML5中文学习网 - HTML5先行者学习网

其实要想真正对这个问题有更深入的理解那么必须对Javascript的作用域和作用域链有深入的理解。PaGHTML5中文学习网 - HTML5先行者学习网

作用域,顾名思义就是指某一属性或方法具有访问权限的代码空间,简单的说也就是这个变量或方法它在代码中的的适用范围。在大多数的OOP中主要有public,private,protect三种作用域,对着三种作用域在这里就不详细解释了,如果有OOP的经验应该都有深入的了解。在这里我要说的是这三种作用域类型对Javascript来说几乎是毫无意义的,因为Javascript中只有一种公共作用域,在Javascript中作用域是在函数中进行维护的。举个例子:PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
var test1='globle variable';PaGHTML5中文学习网 - HTML5先行者学习网
function example(){PaGHTML5中文学习网 - HTML5先行者学习网
var test2='example variable';PaGHTML5中文学习网 - HTML5先行者学习网
alert(test1);PaGHTML5中文学习网 - HTML5先行者学习网
alert(test2);PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
example();PaGHTML5中文学习网 - HTML5先行者学习网
alert(test1);PaGHTML5中文学习网 - HTML5先行者学习网
alert(test2);PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

根据我们前面解释的,这里的test1变量相当于window的一个属性,所以它会在整个window作用域内起作用,而test2则在example()函数的内部声明,所以它的作用域也就维持在example()方法的内部,如果在函数的外部调用test2浏览器会提示出错。而在example()内部调用test1则没问题。PaGHTML5中文学习网 - HTML5先行者学习网

根据这个我们再举一个例子:PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
var test='globle variable';PaGHTML5中文学习网 - HTML5先行者学习网
function example(){PaGHTML5中文学习网 - HTML5先行者学习网
var test='example variable';PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
example();PaGHTML5中文学习网 - HTML5先行者学习网
alert(test);PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

这个例子运行会是什么结果呢?对,警告框会提示“globle variable”,因为example()函数内部的test变量其作用域只维持在内部,不会影响外部的test变量。如果我们将example()内部test变量的var关键字去掉呢?你可以自己试试。PaGHTML5中文学习网 - HTML5先行者学习网

说到这就有牵扯出另外一个概念,那就是作用域链的概念。作用域链就是可以确定变量值的路径。由上面一个例子可以看出,var关键字是用来维护作用域链的,如果变量使用了var关键字声明那么他就可以看作为作用域链的终点。同样函数的形参的定义也会起到类似的作用。PaGHTML5中文学习网 - HTML5先行者学习网

说到这你对this这个精灵古怪的家伙有了比较清晰的认识了吧?根据它简单的一个诠释,this总是指向调用它所在函数的对象,根据作用域和作用域链,我们会很清晰的确定this的真面目。临末尾再来一个开始那个例子的简单变化:PaGHTML5中文学习网 - HTML5先行者学习网

复制代码 代码如下:
PaGHTML5中文学习网 - HTML5先行者学习网
function test(){PaGHTML5中文学习网 - HTML5先行者学习网
alert(this);PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
var obj=function(){PaGHTML5中文学习网 - HTML5先行者学习网
var name='testObj';PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
obj.objTest=test;PaGHTML5中文学习网 - HTML5先行者学习网
obj.objTest2=function(){PaGHTML5中文学习网 - HTML5先行者学习网
test();PaGHTML5中文学习网 - HTML5先行者学习网
}PaGHTML5中文学习网 - HTML5先行者学习网
test();PaGHTML5中文学习网 - HTML5先行者学习网
obj.objTest();PaGHTML5中文学习网 - HTML5先行者学习网
obj.objTest2();PaGHTML5中文学习网 - HTML5先行者学习网
PaGHTML5中文学习网 - HTML5先行者学习网

你猜会提示什么内容呢?你可以运行一下试试(:P);PaGHTML5中文学习网 - HTML5先行者学习网

既然this是根据调用其所在函数的对象的改变而改变的,那我们可不可以强制改变它的调用对象呢?答案是肯定的,以后的文章会介绍一下这部分内容,以及Javascript中不同类型的数据成员的实现方式,闭包等概念。PaGHTML5中文学习网 - HTML5先行者学习网

本人在学习过程中的一些经验和心得体会,写出来一是与大家分享另外也能检视自己的不足,如写的有问题还请批评指教,甚为感谢!PaGHTML5中文学习网 - HTML5先行者学习网

(责任编辑:)
推荐书籍
推荐资讯
关于HTML5先行者 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助