关于javascript中this关键字(翻译+自我理解)


Posted in Javascript onOctober 20, 2010

下文有大概70%的内容出自http://www.quirksmode.org/js/this.html,另外30%是我自己对它的理解和感想。希望能对有需要的人一点帮助。。。

首先,先看一个很典型的关于this关键字题目:

var name = 'hong' 
var obj = { 
name: 'ru', 
getName: function(){ 
return function(){ 
return this.name; 
}; 
} 
} 
alert(obj.getName()());

这里也不卖关子了,执行结果为:hong
稍微改下代码:
var name = 'hong' 
var obj = { 
name: 'ru', 
getName: function(){ 
var that = this; 
return function(){ 
return that.name; 
}; 
} 
} 
alert(obj.getName()());

执行结果为:ru
执行结果为:ru

关于出现这种结果的原因,下面会细细讨论。
【函数的拥有者】
要解释this,要先说这个概念。在JavaScript里,this始终指向我们当前正在执行的函数的“拥有者”。更为确切的说:是指向把这个函数作为方法的对象。
这句话怎么理解,我们可以看看下面的例子:

/* -- test1 -- */ 
function test1 () { 
this.title = 'me'; 
alert(window['title']); 
alert(this === window); //true 
} 
test1();

执行结果为:me, true
在上例中,this是指向window对象的。并把window这个对象的title属性写为'me',因为test1是个顶级函数,所以它的拥有者是window对象,或者说它是window对象的一个方法。这个应该不难理解。比如上面调用test1()时,也可以写成 window.test1();这样的明了了。

接下来,我们建一个div,并把test1作为方法赋给div的onclick属性:

<div id="o" style="width:50px;height:50px;border:4px solid #333">me!</div> 
<script type="text/javascript"> 
/* -- test1 -- */ 
function test1 () { 
this.title = 'me'; 
alert(window['title']); 
alert(this === window); 
} 
var o = document.getElementById('o'); 
o.onclick = test1; 
</script>

点击div结果为:undefined, false; 同时我们用firebug可以看到‘me'这个属性值其实是被赋给了id为‘o'的这个HtmlObject
关于javascript中this关键字(翻译+自我理解)
显而易见,此时this指向了这个div,也就是说,test1()的拥有者变成了div这个HtmlObject,或者说它变成了div的onclick方法来调用。这种情况应该还是容易理解的。
下面我们接着改代码,就改一个地方:
o.onclick = test1(); // 注意:这里加了个括号

把上面代码的最后一句改成这样后,点击div运行的结果为:me, true
变成了和第一种情况一样了,this指向了window。有人会纳闷,觉得没什么区别,其实是有区别的。这里涉及到函数的copy和refer的问题。

【函数的Copy】

如果通过

o.onclick = test1;

这样的方式的话,其实是把test1() 这个函数Copy给了对象 o 的 onclick 属性。因此test1的拥有者变成了 o 这个对象。

如果通过

o.onclick = test1();

这样的方式的话,本质上是指当获取到点击事件的handle时,指引它去执行test1()函数。注意是指引去执行而不是赋给它去执行。test1()的拥有者没变,还是window.

【函数的Refer】

同上,我们通过inline的方式把调用写到html里来调用的话,还是refer的方式

<div id="o" style="width:50px;height:50px;border:4px solid #333" onclick="test1()">me!</div>

点击div执行结果还是表示this指向window。

【函数copy的例子】

element.onclick = doSomething 
element.addEventListener('click',doSomething,false) 
element.onclick = function () {this.style.color = '#cc0000';} 
<element onclick="this.style.color = '#cc0000';">

这几种方式都会使this的指向变为当前调用的object。

【函数refer的例子】

element.onclick = function () {doSomething()} 
element.attachEvent('onclick',doSomething) 
<element onclick="doSomething()">

这几种方式都不会改变函数的拥有者,其中要注意的是addEventListener和attachEvent是不一致的,因为attachEvent其实是建立了一个reference到了doSomething,而不是copy了这个函数。

【用call的方式】
刚才我们说了,写成<element onclick="test()">的方式还是不能让test()的拥有者变成<element>,那我们可以这样做

<element onclick="test(this)"> 
function (o) { 
o.title = 'me'; 
}

这样显式的调用是可以的。或者,用call或apply这种对象冒充的继承方式也可以
<element onclick="test.call(this)"> 
function test () { 
this.title = 'me'; 
}

这也是对象冒充最典型的方式。

【自由变量问题】

写了这么长,我们还是回到最开始的那个问题:

var name = 'hong' 
var obj = { 
name: 'ru', 
getName: function(){ 
return function(){ 
return this.name; 
}; 
} 
} 
alert(obj.getName()());

为什么这种方式得到的结果会是:hong 呢?重点在
return function(){ 
return this.name; 
};

对比一下上面写的函数refer的例子,不难发现,返回的这个匿名函数的调用方式和onclick = function () {doSomething()} 如出一辙。所以这种方式并不会改变这个function的拥有者,它虽然是个嵌套函数,但是它的声明却是顶级的。其中的this指向的是window。

而第二种方式是强制在getName()中把this赋给了that,也就是说,that.name其实和getName()中的this.name是一样的。而在getName的上下文中,它的拥有者是obj这个对象,所以this会指向obj,故this.name === obj.name;

绕了这么一大圈不知道有没有把各位绕明白。

其实可以这样总结:在this所在的函数上下文中,如果这个函数不是以“方法”的形式被调用的话,那么这个this会指向window对象,否则会指向这个函数的拥有者。

Javascript 相关文章推荐
js 深拷贝函数
Dec 04 Javascript
提升你网站水平的jQuery插件集合推荐
Apr 19 Javascript
stream.js 一个很小、完全独立的Javascript类库
Oct 28 Javascript
JavaScript instanceof 的使用方法示例介绍
Oct 23 Javascript
jquery选择checked在ie8普通模式下的问题
Feb 12 Javascript
jQuery实现文本框邮箱输入自动补全效果
Nov 17 Javascript
js使用cookie记录用户名的方法
Nov 26 Javascript
浅析jQuery中使用$所引发的问题
May 29 Javascript
jQuery实现的tab标签切换效果示例
Sep 05 Javascript
AngularJS 实现购物车全选反选功能
Oct 24 Javascript
Angular5中提取公共组件之radio list的实例代码
Jul 10 Javascript
微信小程序自定义toast的实现代码
Nov 16 Javascript
javascript动态改变img的src属性图片不显示的解决方法
Oct 20 #Javascript
javascript奇异的arguments分析
Oct 20 #Javascript
超越Jquery_01_isPlainObject分析与重构
Oct 20 #Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
Oct 20 #Javascript
理解Javascript_14_函数形式参数与arguments
Oct 20 #Javascript
理解Javascript_13_执行模型详解
Oct 20 #Javascript
用jquery与css打造个性化的单选框和复选框
Oct 20 #Javascript
You might like
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
用PHP的超级变量$_POST获取HTML表单(HTML Form) 数据
2011/05/07 PHP
深入PHP许愿墙模块功能分析
2013/06/25 PHP
destoon在各个服务器下设置URL Rewrite(伪静态)的方法
2014/06/21 Servers
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
2016/07/02 PHP
php+jquery+html实现点击不刷新加载更多的实例代码
2016/08/12 PHP
php、java、android、ios通用的3des方法(推荐)
2016/09/09 PHP
laravel-admin 在列表页添加自定义按钮的例子
2019/09/30 PHP
js 颜色选择器(兼容firefox)
2009/03/05 Javascript
js函数中onmousedown和onclick的区别和联系探讨
2013/05/19 Javascript
js实现的折叠导航示例
2013/11/29 Javascript
判断javascript的数据类型(示例代码)
2013/12/11 Javascript
JS实现控制表格行内容垂直对齐的方法
2015/03/30 Javascript
JS对字符串编码的几种方式使用指南
2015/05/14 Javascript
Bootstrap每天必学之js插件
2015/11/30 Javascript
jQuery+css实现的tab切换标签(兼容各浏览器)
2016/01/28 Javascript
JS日程管理插件FullCalendar中文说明文档
2017/02/06 Javascript
JavaScript实现多重继承的方法分析
2018/01/09 Javascript
微信小程序获取用户信息并保存登录状态详解
2019/05/10 Javascript
vue.js实现二级菜单效果
2019/10/19 Javascript
Java Varargs 可变参数用法详解
2020/01/28 Javascript
如何编写一个 Webpack Loader的实现
2020/10/18 Javascript
python同步两个文件夹下的内容
2019/08/29 Python
使用PyCharm安装pytest及requests的问题
2020/07/31 Python
全球销量第一生发产品:Viviscal
2017/12/21 全球购物
荷兰包包购物网站:The Little Green Bag
2018/03/17 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
开展党的群众路线教育实践活动方案
2014/02/05 职场文书
工业自动化专业自荐信范文
2014/04/10 职场文书
小学班主任评语大全
2014/04/23 职场文书
2014年企业工会工作总结
2014/11/12 职场文书
我的中国梦主题教育活动总结
2015/05/07 职场文书
《最后一头战象》读后感:动物也有感情
2020/01/02 职场文书
读《茶花女》有感:山茶花的盛开与凋零
2020/01/17 职场文书
APP界面设计技巧和注意事项
2022/04/29 杂记
华为HarmonyOS3.0强在哪? 看看鸿蒙3.0这7个小功能
2023/01/09 数码科技