zoukankan      html  css  js  c++  java
  • js中的this

    http://www.jb51.net/article/41656.htm

    https://www.cnblogs.com/lisha-better/p/5684844.html

    https://www.ibm.com/developerworks/cn/web/1207_wangqf_jsthis/index.html

    http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_this_in_javascript.html

    this是Javascript语言的一个关键字它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用,下面分四种情况,详细讨论this的用法
     
    this是Javascript语言的一个关键字。 
    它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用。比如, 
    代码如下:

      function test(){ 

        this.x = 1; 

      } 

    随着函数使用场合的不同,this的值会发生变化。但是有一个总的原则,那就是this指的是,调用函数的那个对象。 也就是说,一般而言,在Javascript中,this指向函数执行时的当前对象。

    函数的执行环境

    JavaScript 中的函数既可以被当作普通函数执行,也可以作为对象的方法执行,这是导致 this 含义如此丰富的主要原因。一个函数被执行时,会创建一个执行环境(ExecutionContext),函数的所有的行为均发生在此执行环境中,构建该执行环境时,JavaScript 首先会创建 arguments变量,其中包含调用函数时传入的参数。接下来创建作用域链。然后初始化变量,首先初始化函数的形参表,值为 arguments变量中对应的值,如果 arguments变量中没有对应值,则该形参初始化为 undefined。如果该函数中含有内部函数,则初始化这些内部函数。如果没有,继续初始化该函数内定义的局部变量,需要注意的是此时这些变量初始化为 undefined,其赋值操作在执行环境(ExecutionContext)创建成功后,函数执行时才会执行,这点对于我们理解 JavaScript 中的变量作用域非常重要,鉴于篇幅,我们先不在这里讨论这个话题。最后为 this变量赋值,如前所述,会根据函数调用方式的不同,赋给 this全局对象,当前对象等。至此函数的执行环境(ExecutionContext)创建成功,函数开始逐行执行,所需变量均从之前构建好的执行环境(ExecutionContext)中读取。



    下面分四种情况,详细讨论this的用法。 

    情况一:纯粹的函数调用 

    这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global。 

    请看下面这段代码,它的运行结果是1。 
    复制代码代码如下:

      function test(){ 

        this.x = 1; 

        alert(this.x); 

      } 

      test(); // 1 

    为了证明this就是全局对象,我对代码做一些改变: 
    代码如下:

      var x = 1; 

      function test(){ 

        alert(this.x); 

      } 

      test(); // 1 

    运行结果还是1。再变一下: 
    代码如下:

      var x = 1; 

      function test(){ 

        this.x = 0; 

      } 

      test(); 

      alert(x); //0 

    情况二:作为对象方法的调用 

    函数还可以作为某个对象的方法调用,这时this就指这个上级对象。 
    代码如下:

      function test(){ 

        alert(this.x); 

      } 

      var o = {}; 

      o.x = 1; 

      o.m = test; 

      o.m(); // 1 

    情况三 作为构造函数调用 

    所谓构造函数,就是通过这个函数生成一个新对象(object)。这时,this就指这个新对象。 
    代码如下:

      function test(){ 

        this.x = 1; 

      } 

      var o = new test(); 

      alert(o.x); // 1 

    运行结果为1。为了表明这时this不是全局对象,我对代码做一些改变: 
    代码如下:

      var x = 2; 

      function test(){ 

        this.x = 1; 

      } 

      var o = new test(); 

      alert(x); //2 

    运行结果为2,表明全局变量x的值根本没变。 

    情况四 apply调用 

    apply()是函数对象的一个方法,它的作用是改变函数的调用对象,它的第一个参数就表示改变后的调用这个函数的对象。因此,this指的就是这第一个参数。 
    代码如下:

      var x = 0; 

      function test(){ 

        alert(this.x); 

      } 

      var o={}; 

      o.x = 1; 

      o.m = test; 

      o.m.apply(); //0 

    apply()的参数为空时,默认调用全局对象。因此,这时的运行结果为0,证明this指的是全局对象。 

    如果把最后一行代码修改为 
    代码如下:

    o.m.apply(o); //1

    运行结果就变成了1,证明了这时this代表的是对象o

    情况五:Function.prototype.bind()方法

     
        var name="XL";
        function Person(name){
            this.name=name;
            this.sayName=function(){
                setTimeout(function(){
                    console.log("my name is "+this.name);
                },50)
            }
        }
        var person=new Person("xl");
        person.sayName()  //输出  “my name is XL”;
                           //这里的setTimeout()定时函数,相当于window.setTimeout(),由window这个全局对象对调用,因此this的指向为window, 则this.name则为XL 
     

    那么如何才能输出"my name is xl"呢?

        var name="XL";
        function Person(name){
            this.name=name;
            this.sayName=function(){
                setTimeout(function(){
                    console.log("my name is "+this.name);
                }.bind(this),50)  //注意这个地方使用的bind()方法,绑定setTimeout里面的匿名函数的this一直指向Person对象
            }
        }
        var person=new Person("xl");
        person.sayName(); //输出 “my name is xl”;
     

    这里setTimeout(function(){console.log(this.name)}.bind(this),50);,匿名函数使用bind(this)方法后创建了新的函数,这个新的函数不管在什么地方执行,this都指向的Person,而非window,因此最后的输出为"my name is xl"而不是"my name is XL"

    另外几个需要注意的地方:
    情况六:setTimeout/setInterval/匿名函数执行的时候,this默认指向window对象,除非手动改变this的指向。在《javascript高级程序设计》当中,写到:“超时调用的代码(setTimeout)都是在全局作用域中执行的,因此函数中的this的值,在非严格模式下是指向window对象,在严格模式下是指向undefined”。本文都是在非严格模式下的情况。

      var name="XL";
        function Person(){
            this.name="xl";
            this.showName=function(){
                console.log(this.name);
            }
            setTimeout(this.showName,50);
        }
        var person=new Person(); //输出 "XL"
        
        //在setTimeout(this.showName,50)语句中,会延时执行this.showName方法
        //this.showName方法即构造函数Person()里面定义的方法。50ms后,执行this.showName方法,this.showName里面的this此时便指向了window对象。则会输出"XL";
     

    修改上面的代码:

     
     
     1   var name="XL";
     2     function Person(){
     3         this.name="xl";
     4         var that=this;
     5         this.showName=function(){
     6             console.log(that.name);
     7         }
     8         setTimeout(this.showName,50)
     9     }
    10     var person=new Person(); //输出 "xl"
    11 
    12 
    13 
    14     //这里在Person函数当中将this赋值给that,即让that保存Person对象,因此在setTimeout(this.showName,50)执行过程当中,console.log(that.name)即会输出Person对象的属性"xl"

    匿名函数:

     1   var name="XL";
     2     var person={
     3         name:"xl",
     4         showName:function(){
     5             console.log(this.name);
     6         }
     7         sayName:function(){
     8             (function(callback){
     9                 callback();
    10             })(this.showName)
    11         }
    12     }
    13     person.sayName();  //输出 XL
    14     var name="XL";
    15     var person={
    16         name:"xl",
    17         showName:function(){
    18             console.log(this.name);
    19         }
    20         sayName:function(){
    21             var that=this;
    22             (function(callback){
    23                 callback();
    24             })(that.showName)
    25         }
    26     }
    27     person.sayName() ;  //输出  "xl"
    28     //匿名函数的执行同样在默认情况下this是指向window的,除非手动改变this的绑定对象
     

    情况七:Eval函数

    该函数执行的时候,this绑定到当前作用域的对象上。JavaScript 中的 eval 方法可以将字符串转换为 JavaScript 代码,使用 eval 方法时,this 指向哪里呢?答案很简单,看谁在调用 eval 方法,调用者的执行环境(ExecutionContext)中的 this 就被 eval 方法继承下来了。

        var name="XL";
        var person={
            name:"xl",
            showName:function(){
                eval("console.log(this.name)");
            }
        }
        
        person.showName();  //输出  "xl"
        
        var a=person.showName;
        a();  //输出  "XL"
     

    情况八:箭头函数

    es6里面this指向固定化,始终指向外部对象,因为箭头函数没有this,因此它自身不能进行new实例化,同时也不能使用call, apply, bind等方法来改变this的指向

       function Timer() {
            this.seconds = 0;
            setInterval( () => this.seconds ++, 1000);
        } 
        
        var timer = new Timer();
        
        setTimeout( () => console.log(timer.seconds), 3100);
        
        // 3
       // 在构造函数内部的setInterval()内的回调函数,this始终指向实例化的对象,并获取实例化对象的seconds的属性,每1s这个属性的值都会增加1。否则最后在3s后执行setTimeOut()函数执行后输出的是0
     
  • 相关阅读:
    存图方式---邻接表&邻接矩阵&前向星
    Bellman-Ford算法的改进---SPFA算法
    POJ-2240 Arbitrage---判断正环+枚举
    POJ-1860 Currency Exchange---Bellman-Ford判断正环
    单源最短路径---Bellman-Ford算法
    ZOJ-2750 Idiomatic Phrases Game---Dijk最短路
    POJ-1135 Domino Effect---最短路Dijk
    单源最短路径---Dijkstra算法
    POJ-1679 The Unique MST---判断最小生成树是否唯一
    POJ-2031 Building a Space Station---MST + 空间距离
  • 原文地址:https://www.cnblogs.com/dyh-air/p/7898278.html
Copyright © 2011-2022 走看看