我在学习JS初期,在使用this的时候经常出现问题,当然就是在现在,也有一些场景不能很好的明白this到底指代的是什么?看下面一个例子:
  

  1. var x = 10;
  2. var foo = {
  3. x: 20,
  4. bar: function() {
  5. alert(this.x);
  6. }
  7. }
  8. var bar = foo.bar;
  9. foo.bar(); //20
  10. bar(); //10

  

    其实最开始我想的结果都应该是20的,因为都是foo对象的方法,该方法调用的时候,this当然指的就是foo本身吗?其实这个观点是错误的,直到今天我才稍稍的明白了,this到底指的是什么?怎么才能找到正确的this。
 
    有一种说法是:this是在函数定义的时候就确定好的,其实这种说法是有问题。事实上this是在代码执行的过程中才被定义,并且不能通过赋值的方法进行改变。下面举一个简单的例子:

  1. function bar() {
  2. console.log(this);
  3. }
  4. bar(); //window 其实是global对象
  5. console.log(bar === bar.prototype.constructor); //true
  6. bar.prototype.constructor(); //bar.prototype
 
    如果按照上面的说法,上面this永远都是window,不会变成bar.prototype。其实我并没有改变什么,只是改变了调用方式,所以在不同的执行上下文中,this的值是不相同,那么到底是根据什么来确定this呢?
 
    在讲解之前,熟悉一个概念:引用类型。什么是引用类型呢?在ECMAScript里头,引用类型就是用来保存数据和方法的,别的语言称之为"类"(Class)。虽说ECMAScript是面向对象的语言,但在ECMAScript里,缺少面向对象的概念——类和接口。所以,ECMAScript里不能称为类,我们称为:对象定义。引用类型的值就是一个实例化的对象,我们会通过构造函数来实例化对象进行操作。
 
    this值的存在,必然是伴随这函数的执行。如果这个函数是引用类型,那么this就是该引用类型;如果不是引用类型,this就是null,此时会被隐式的转换成全局对象global(表现为window)对象。更详细的解释是:
  

  1. The value of this in a function context is provided by the caller and determined by the current form of a call expression (how the function call is written syntactically).
  2.  
  3. If on the left hand side from the call parentheses ( ... ), there is a value of Reference type then this value is set to the base object of this value of Reference type.
  4.  
  5. In all other cases (i.e. with any other value type which is distinct from the Reference type), thisvalue is always set to null. But since there is no any sense in null for this value, it is implicitlyconverted to global object.

  

    那么来看一个经典的例子:

  1. var foo = {
  2. bar: function () {
  3.  
  4. console.log(this);
  5.  
  6. }
  7.  
  8. };
  9. foo.bar(); // Reference, OK => foo
  10.  
  11. (foo.bar)(); // Reference, OK => foo
  12.  
  13. (foo.bar = foo.bar)(); // global
  14.  
  15. (false || foo.bar)(); // global
  16.  
  17. (foo.bar, foo.bar)(); // global

  

    首先需要了解的是()操作符,组操作符只是分组,不会改变数据的类型;并且在运算的时候,会改变优先级;其次就是函数执行的时候会使用()。
    第一个和第二个很明显左边的都是引用类型
    之所以,后三个改变了this,是因为=、||、,等运算符会改变引用类型为普通的函数对象,此时this都为null,都会被隐式的转化成global对象。
 
    说了这么多,可能对this,有了进一步的了解。之前说了,不能通过赋值的方法改变this的值,那可以通过什么途径改变呢?唯一的途径就是改变它的执行上下文(调用函数的方式),那有哪些方法可以改变执行上下文呢?
 
    定义一个构造函数
  

  1. function person() {
  2. console.log(this);
  3. }
  4. person(); //window(global)

  

    1.通过new方法,可以将this改编成该实例化对象
    2.通过call或者apply可以改变成新的对象
    
    最后一点,在执行上下文中,this永运不会为null或者undefined(可能这种表达方式有点儿为问题,这里指的是最终表现),要么是引用类型的值,要么是global对象(一方面本身就是global对象,另一方面会将null隐式转换成global对象)。
    
    本身也是学习阶段,可能会有理解不清楚的地方,希望给位不吝赐教。
 
    参考文献:
    http://www.cnblogs.com/jkisjk/archive/2011/01/30/javascript_this.html
    
    
 
 

JS中简单的this学习的更多相关文章

  1. [转] JS中简单的继承与多态

    这里讲了一个最最最简单的JS中基于原型链的继承和多态. 先看一下以下这段代码的实现(A是“父类”,B是“子类”): var A = function(){ this.value = 'a'; this ...

  2. 在JS中简单实现Formatter函数

    JS原生并没有提供方便使用的Formatter函数,用字符拼接的方式看起来混乱难读,而且使用起来很不方便.个人感觉C#里提供的语法比较好用,如: String.Format("Welcome ...

  3. JS中的bind方法学习

    EcmaScript5给Function扩展了一个方法:bind 众所周知 在jQuery和prototype.js之类的框架里都有个bind jQuery里的用途是给元素绑定事件 $("# ...

  4. 1.1 js中函数定义解析(学习笔记)

    1.1.1函数的分类 函数声明式 :使用function声明函数,并指定函数名. 函数表达式:使用function声明函数,但未指定函数名. 函数表达式2.匿名函数,匿名函数有很多作用,赋予一个变量则 ...

  5. JS中简单的二级城市联动

    代码奉上: <!DOCTYPE html><html><head>    <meta charset="UTF-8">    < ...

  6. JS中简单原型的使用

  7. js中简单操作

    去空格:ss.replace(/\s/g,""); 数组: 千万不能用in操作符 in 是说存不存在这个key而不是value! var a = [66,99,77]; 66 in ...

  8. 深入探究js中无所不在的this

    黄金守则: this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window而当函数被作为某个对象的方法调用时, this等于那个对象. 下面是一些相关实践: --------- ...

  9. Node.js中的Session,不要觉得简单哦。

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,博客地址为http://www.cnblogs.com/jasonnode/ .学习网站上有对应 ...

随机推荐

  1. python3-day3(内置函数)

    1.内置函数 1>print(bytearray('王',encoding='utf8')) 2>print(bytes('王',encoding='utf8')) 3>bool(' ...

  2. Javascript 文件操作(整理版)

    Javascript 文件操作 一.功能实现核心:FileSystemObject 对象 其实,要在Javascript中实现文件操作功能,主要就是依靠FileSystemobject对象.在详细介绍 ...

  3. UGUI 全方位了解

    随着 unity3d 4.6 ~ 5.x + 新 UI 系统最终与大家见面了.这篇文章将不会介绍怎样使用button.滚动栏之类的UI控件.这些内容能够參考Unity Manual:这篇文章的重点是. ...

  4. Linux内核设计基础(十)之内核开发与总结

    (1)Linux层次结构: (2)Linux内核组成: 主要由进程调度(SCHED).内存管理(MM).虚拟文件系统(VFS).网络接口(NET)和进程间通信(IPC)等5个子系统组成. (3)与Un ...

  5. 利用JS实现简单的瀑布流效果

    哈哈, 我又来啦, 在这一段时间里, 我简单的学习了一下javascript(JS), 虽然不是很懂啦, 但是我也简单的尝试着做了点小东西, 就比如现在流行的瀑布流效果, 经过我的努力终于成功的完成了 ...

  6. cookie 和 session

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  7. C#中public、private、protected、internal、protected internal (转载)

    在C#语言中,共有五种访问修饰符:public.private.protected.internal.protected internal.作用范围如下表:访问修饰符 说明public 公有访问.不受 ...

  8. Mac_配置adb环境变量

    1.打开终端Terminal. 2.进入HOME目录:命令行输入 echo(这之间有一个空格) $HOME 3.创建.bash_profile文件:命令行输入 touch(这之间有一个空格).bash ...

  9. iOS开发中遇到的一些问题及解决方案【转载】

    iOS开发中遇到的一些问题及解决方案[转载] 2015-12-29 [385][scrollView不接受点击事件,是因为事件传递失败] // //  MyScrollView.m //  Creat ...

  10. MFC线程(三):线程同步事件(event)与互斥(mutex)

    前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFu ...