正确理解javascript的this关键字
javascript有this关键字,this跟javascript的执行上下文密切相关,很多前端开发工程师至今对this关键字还是模棱两可,本文将结合代码讲解下javascript的this关键字。
this和对象的关系
首先来看下面的代码:
var person = { name:'Theo Wong', gender:'male', getName:function(){ console.log(person.name); } }; person.getName();
定义了一个person对象,对象中包含了name、gender属性,还包括了一个getName的方法,其作用是输出person对象的name。在这种情况下,我们可以使用this来在person对象中代替person对象本身,所以上面的代码跟下面的直接结果是一样的:
var person = { name:'Theo Wong', gender:'male', getName:function(){ console.log(this.name); } }; person.getName();
请记住一点:this永远指向的是函数对象的所有者!上面的例子中getName的所有者是person对象,所以this指代的是person。
this和全局对象
我们再来看看再全局对象中,this指代的是什么,我们知道javascript是脚本语言,所以javascript的执行需要有一个宿主环境,在浏览器中这个宿主环境就是window对象,所以在全局函数中,this指代的是window对象(除非使用new,call,apply方法来改变this的指代关系)。懂得了这个关键点,下面的代码就好理解了:
var a = 1; console.log(a);//1 console.log(this.a);//1 console.log(window.a);//1
很多前端开发工程师经常使用在函数名字之前添加个window来调用函数,这是因为在浏览器中全局对象就是window,所有的函数变量都是在window对象之中,所以下面的代码中的this指代window对象就好理解了:
var a = 1; function foo(){ var b = 2; console.log(this.a+b);//3 } foo();
所以说,只要记住:this永远指向的是函数对象的所有者,即this的值是由激活执行上下文代码的调用者决定的,就好理解this的指代关系了。
函数构造器中的this
当函数作为构造器使用new关键字实例化时,this的指代关系又是怎样的呢?看下面的代码:
var Person = function(){ this.name = 'Theo Wong'; } var person = new Person(); console.log(person.name);
new执行过程会首先执行Person的构造器[[construct]],然后在调用[[call]]方法给this赋值,这个执行过程可以简单理解为三步
所以经过new加工过的函数,this的函数调用者是Person本身,而不是window了。
嵌套函数中的this
在嵌套函数中,this的指代关系有会是怎样的呢?看下面的代码:
var myObject = { func1:function() { console.log(this); //myObject var func2=function() { console.log(this); //window var func3=function() { console.log(this); //window }(); }(); } }; myObject.func1();
在嵌套函数中,由于嵌套函数的执行上下文是window,所以this指代的是window对象,其实这是ECMA-262-3的一个bug,在最新的ECMA-262-5中已经修复。
事件处理中的this
在javascript中处理事件函数中,this的指代关系就更加扑朔离迷了。我们建立一个showValue函数,函数内容如下:
var showValue = function(){ console.log(this.value); };
现在有个input,我们给input元素添加click事件,当点击input时触发showValue函数,看看现在的this指代的是什么对象。
通过dom.onclick绑定事件
document.getElementById('test').onclick = showValue;
运行代码会得到预期的结果,showValue虽然定义在全局对象中,但是当采用了onclick的绑定方式时,showValue是作为dom的onclick方法被调用的,所以它的this应该指代的是dom对象,而不再是window对象。
写在html标签内
当点击dom时,我们获取不到正确的this,这是为什么呢?
此时的this指代的是window对象,因为window对象中没有定义value的值,所以获取不到this.value。其实此时的不是将showValue函数赋值给dom对象的onclick,而是引用!所以上面的代码跟下面的代码关系是一样的:
document.getElementById('test').onclick = function(){ showValue(); };
根据上面说的javascript嵌套函数的this值,我们可以得出现在showValue的this其实是window。
通过addEventListener/attachEvent绑定事件监听
这种绑定事件监听的方式,attachEvent this是window对象,而addEventListener则是dom对象的。@魔堕轮回 提出来的bug~嘎嘎
使用call和apply方法改变this
在Function对象原型(Function.prototype)中有两个方法:call和apply,通过call和apply可以改变this的值, 它们都接受第一个参数作为调用执行上下文中this的值。它们的不同点就是apply第二个参数为数组,call接收的参数是依次传入的。
var obj = { name:'Theo Wong', desc:'一个前端开发者' }; var getInfo = function(){ console.log(this.name+this.desc); }; getInfo.call(obj); //Theo Wong一个前端开发者
总结
this是javascript的重要关键字,理解掌握this关键字在不同的执行上下文指代关系,才能避免代码犯一些不必要的错误。深入了解javascript的代码执行过程,及其执行上下文,推荐阅读《javascript的词法作用域》
建议继续学习:
- 揭秘JavaScript中谜一样的this (阅读:3699)
- jQuery之不要滥用$(this) (阅读:2506)
- JavaScript中的this关键字 (阅读:2443)
- 深入理解Javascript之this关键字 (阅读:2205)
- Javascript中的this (阅读:2226)
- 匿名类型的硬伤:围绕this的成员捕获策略 (阅读:1829)
- 匿名类型的硬伤:围绕this的成员捕获策略 (阅读:1682)
- Javascript的this用法 (阅读:1630)
- 理解JavaScript 中的 this (阅读:1538)
- 关于回调函数和this指针探讨 (阅读:1437)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:三水清 来源: 三水清
- 标签: this
- 发布时间:2011-11-16 00:12:45
- [68] Twitter/微博客的学习摘要
- [66] IOS安全–浅谈关于IOS加固的几种方法
- [64] android 开发入门
- [64] 如何拿下简短的域名
- [62] find命令的一点注意事项
- [61] Go Reflect 性能
- [60] 流程管理与用户研究
- [59] Oracle MTS模式下 进程地址与会话信
- [58] 图书馆的世界纪录
- [56] 读书笔记-壹百度:百度十年千倍的29条法则