JavaScript有this关键字,this跟JavaScript的执行上下文密切相关,很多前端开发工程师至今对this关键字还是模棱两可,本文将结合代码讲解下JavaScript的this关键字

this和对象的关系

首先来看下面的代码:

  1. var person = {
  2. name:'Theo Wong',
  3. gender:'male',
  4. getName:function(){
  5. console.log(person.name);
  6. }
  7. };
  8. person.getName();

定义了一个person对象,对象中包含了name、gender属性,还包括了一个getName的方法,其作用是输出person对象的name。在 这种情况下,我们可以使用this来在person对象中代替person对象本身,所以上面的代码跟下面的直接结果是一样的:

  1. var person = {
  2. name:'Theo Wong',
  3. gender:'male',
  4. getName:function(){
  5. console.log(this.name);
  6. }
  7. };
  8. person.getName();

请记住一点:this永远指向的是函数所属的对象!上面的例子中getName的所属的对象是person对象,所以this指代的是person。

this和全局对象

我们再来看看再全局对象中,this指代的是什么,我们知道JavaScript是脚本语言,所以JavaScript的执行需要有一个宿主环境, 在浏览器中这个宿主环境就是window对象,所以在全局函数中,this指代的是window对象(除非使用new,call,apply方法来改变 this的指代关系)。懂得了这个关键点,下面的代码就好理解了:

  1. var a = 1;
  2. console.log(a);//1
  3. console.log(this.a);//1
  4. console.log(window.a);//1

很多前端开发工程师经常使用在函数名字之前添加个window来调用函数,这是因为在浏览器中全局对象就是window,所有的函数变量都是在window对象之中,所以下面的代码中的this指代window对象就好理解了:

  1. var a = 1;
  2. function foo(){
  3. var b = 2;
  4. console.log(this.a+b);//3
  5. }
  6. foo();

所以说,只要记住:this永远指向的是函数对象的所有者,即this的值是由激活执行上下文代码的调用者决定的,就好理解this的指代关系了。

函数构造器中的this

当函数作为构造器使用new关键字实例化时,this的指代关系又是怎样的呢?看下面的代码:

  1. var Person = function(){
  2. this.name = 'Theo Wong';
  3. }
  4. var person = new Person();
  5. console.log(person.name);

new执行过程会首先执行Person的构造器[[construct]],然后在调用[[call]]方法给this赋值,这个执行过程可以简单理解为三步

  1. 首先建立一个空的对象object,类似var obj={}
  2. 然后将空对象使用Person的call操作,类似Person.call(obj)
  3. 执行完Person之后再return this,完成new过程,赋值给person变量

所以经过new加工过的函数,this的函数调用者是Person本身,而不是window了。

嵌套函数中的this

在嵌套函数中,this的指代关系有会是怎样的呢?看下面的代码:

  1. var myObject = {
  2. func1:function() {
  3. console.log(this); //myObject
  4. var func2=function() {
  5. console.log(this); //window
  6. var func3=function() {
  7. console.log(this); //window
  8. }();
  9. }();
  10. }
  11. };
  12. myObject.func1();

在嵌套函数中,由于嵌套函数的执行上下文是window,所以this指代的是window对象,其实这是ECMA-262-3的一个bug,在最新的ECMA-262-5中已经修复。

事件处理中的this

在JavaScript中处理事件函数中,this的指代关系就更加扑朔离迷了。我们建立一个showValue函数,函数内容如下:

  1. var showValue = function(){
  2. console.log(this.value);
  3. };

现在有个input,我们给input元素添加click事件,当点击input时触发showValue函数,看看现在的this指代的是什么对象。

  1. <input id="test" type="text" />

通过dom.onclick绑定事件

  1. document.getElementById('test').onclick = showValue;

运行代码会得到预期的结果,showValue虽然定义在全局对象中,但是当采用了onclick的绑定方式时,showValue是作为dom的onclick方法被调用的,所以它的this应该指代的是dom对象,而不再是window对象。

写在html标签内

  1. <input id="test" type="text" onclick="showValue();" />

当点击dom时,我们获取不到正确的this,这是为什么呢?

此时的this指代的是window对象,因为window对象中没有定义value的值,所以获取不到this.value。其实此时的不是将showValue函数赋值给dom对象的onclick,而是引用!所以上面的代码跟下面的代码关系是一样的:

  1. document.getElementById('test').onclick = function(){
  2. showValue();
  3. };

根据上面说的JavaScript嵌套函数的this值,我们可以得出现在showValue的this其实是window。

通过addEventListener/attachEvent绑定事件监听

  1. <input type="text" id="test" />
  2. <script type="text/JavaScript">
  3. var dom = document.getElementById('test');
  4. id = 'window';
  5. function test(){
  6. alert(this.id);
  7. }
  8. dom.addEventListener ? dom.addEventListener('click', test, false) : dom.attachEvent('onclick', test);
  9. //addEventListener test
  10. //attachEvent window
  11. </script>

这种绑定事件监听的方式,attachEvent this是window对象,而addEventListener则是dom对象的。@魔堕轮回 提出来的bug~嘎嘎

使用call和apply方法改变this

在Function对象原型(Function.prototype)中有两个方法:call和apply,通过call和apply可以改变 this的值, 它们都接受第一个参数作为调用执行上下文中this的值。它们的不同点就是apply第二个参数为数组,call接收的参数是依次传入的。

  1. var obj = {
  2. name:'Theo Wong',
  3. desc:'一个前端开发者'
  4. };
  5. var getInfo = function(){
  6. console.log(this.name+this.desc);
  7. };
  8. getInfo.call(obj);
  9. //Theo Wong一个前端开发者

总结

this是JavaScript的重要关键字,理解掌握this关键字在不同的执行上下文指代关系,才能避免代码犯一些不必要的错误。深入了解JavaScript的代码执行过程,及其执行上下文,推荐阅读《JavaScript的词法作用域

正确理解JavaScript中的this关键字的更多相关文章

  1. 转载 深入理解JavaScript中的this关键字

    转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字   1. 一 ...

  2. 如何理解JavaScript中的this关键字

    前言 王福朋老师的 JavaScript原型和闭包系列 文章看了不下三遍了,最为一个初学者,每次看的时候都会有一种 "大彻大悟" 的感觉,而看完之后却总是一脸懵逼.原型与闭包 可以 ...

  3. 浅显易懂的理解JavaScript中的this关键字

    在JavaScript中this变量是一个令人难以摸清的关键字,this可谓是非常强大,充分了解this的相关知识有助于我们在编写面向对象的JavaScript程序时能够游刃有余. 1. 一般用处 对 ...

  4. 用自然语言的角度理解JavaScript中的this关键字

    转自:http://blog.leapoahead.com/2015/08/31/understanding-js-this-keyword/ 在编写JavaScript应用的时候,我们经常会使用th ...

  5. 深入理解JavaScript中的this关键字

    1. 一般用处 2. this.x 与 apply().call() 3. 无意义(诡异)的this用处 4. 事件监听函数中的this 5. 总结 在JavaScript中this变量是一个令人难以 ...

  6. 理解JavaScript中的this关键字

    JavaScript中this关键字理解 在爬虫的过程中遇到了前端的js代码,对于this关键字理解的不是很清楚,所以写下这篇笔记,不足之处,希望得以改之. this的指向在函数定义的时候无法确定,只 ...

  7. 理解javascript中的with关键字

    说起js中的with关键字,很多小伙伴们的第一印象可能就是with关键字的作用在于改变作用域,然后最关键的一点是不推荐使用with关键字.听到不推荐with关键字后,我们很多人都会忽略掉with关键字 ...

  8. 正确理解javascript的this关键字

    javascript有this关键字,它和javascript的执行上下文有着密切的关系,就是说this具体指代什么要根据它的上下文来判断. 一.this和对象的关系    var Person={ ...

  9. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

随机推荐

  1. 关于adb连接手机offline的问题解决

    win7-64位系统.对于windows系统,adb devices 显示offline一般可能有两个原因: 1 )端口被占用. 解决方式是:查找端口号,结束占用进程: adb nodaemon se ...

  2. 软件工程个人作业 - week1

    <构建之法>阅读疑惑: 如何寻找开发效率和性能的均衡点?显然开发效率强调封装,重视代码重用.但是遗憾的是代码重用往往泛化了数据特征,降低了效率. 如何“公平”分配工作?尤其是团队中人员参差 ...

  3. java学习总结

    1 获得项目绝对路径 String path = request.getContextPath(); String basePath = request.getScheme() + ":// ...

  4. mac OS(OS X)的OI编译环境配置指南

    编译环境:gdb+Atom 如何安装gdb: http://logic0.blog.163.com/blog/static/1889281462014183271283/   Atom下载地址: ht ...

  5. POJ 3678 Katu Puzzle(强连通 法)

    题目链接 题意:给出a, b, c 和操作类型 (与或异或),问是否满足所有的式子 主要是建图: 对于 and , c == 1: 说明 a 和 b都是1,那么 0 就不能取, a' -> a ...

  6. 如何排查APP服务端和客户端是否支持ATS

    服务端排查 取得客户端直接连接的服务端域名及端口,例如mob.com.cn,端口443,即HTTPS默认端口.针对公网可访问的生产环境地址,建议使用的在线监测工具.https://wosign.ssl ...

  7. char *p = "abcdefg"; p[0] = p[1]出错

    参考:http://blog.sina.com.cn/s/blog_5c0172280100ut4o.html 1.char *s="abc"; 看这个赋值: 右边,是" ...

  8. HTML5学习预览

    HTML5中,新增了很多input元素的类型 email         email类型用于应该包含 e-mail 地址的输入域. url         url 类型用于应该包含 URL 地址的输入 ...

  9. python --- Python中的callable 函数

    python --- Python中的callable 函数 转自: http://archive.cnblogs.com/a/1798319/ Python中的callable 函数 callabl ...

  10. Android中怎么用this

    在JAVA程序中似乎经常见到“this”,自己也偶尔用到它,但是到底“this”该怎么用,却心中无数!很多人一提起它,就说“当前对象”,可到底什么是当前对象,是什么当前对象,他自己也不清楚.现在让大家 ...