<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      沙沙起  

      本文主要解釋在JS里面this關鍵字的指向問題(在瀏覽器環境下)。

      閱讀此文章,還需要心平氣和的閱讀完,相信一定會有所收獲,我也會不定期的發布,分享一些文章,共同學習

      首先,必須搞清楚在JS里面,函數的幾種調用方式:

      • 普通函數調用

      • 作為方法來調用

      • 作為構造函數來調用

      • 使用apply/call方法來調用

      • Function.prototype.bind方法

      • es6箭頭函數

      但是不管函數是按哪種方法來調用的,請記住一點:誰調用這個函數或方法,this關鍵字就指向誰

      接下來就分情況來討論下這些不同的情況:

      普通函數調用

      1     function person(){
      2         this.name="xl";
      3         console.log(this);
      4         console.log(this.name);
      5     }
      6     
      7     person();  //輸出  window  xl   
      8     

       

      在這段代碼中person函數作為普通函數調用,實際上person是作為全局對象window的一個方法來進行調用的,即window.person();
      所以這個地方是window對象調用了person方法,那么person函數當中的this即指window,同時window還擁有了另外一個屬性name,值為xl.

      1     var name="xl";
      2     function person(){
      3         console.log(this.name);
      4     }
      5     person(); //輸出 xl

       

      同樣這個地方person作為window的方法來調用,在代碼的一開始定義了一個全局變量name,值為xl,它相當于window的一個屬性,即window.name="xl",又因為在調用person的時候this是指向window的,因此這里會輸出xl.

      作為方法來調用

      在上面的代碼中,普通函數的調用即是作為window對象的方法進行調用。顯然this關鍵字指向了window對象.

      再來看下其他的形式

          var name="XL";
          var person={
              name:"xl",
              showName:function(){
                  console.log(this.name);
              }
          }
          person.showName();  //輸出  xl
         //這里是person對象調用showName方法,很顯然this關鍵字是指向person對象的,所以會輸出name
          
          var showNameA=person.showName;
          showNameA();    //輸出  XL
          //這里將person.showName方法賦給showNameA變量,此時showNameA變量相當于window對象的一個屬性,因此showNameA()執行的時候相當于window.showNameA(),即window對象調用showNameA這個方法,所以this關鍵字指向window

       

      再換種形式:

          var personA={
              name:"xl",
              showName:function(){
                  console.log(this.name);
              }
          }
          var personB={
              name:"XL",
              sayName:personA.showName
          }
          
          personB.sayName();  //輸出 XL
          //雖然showName方法是在personA這個對象中定義,但是調用的時候卻是在personB這個對象中調用,因此this對象指向

       

      作為構造函數來調用

       1     function  Person(name){
       2         this.name=name;
       3     }
       4     var personA=Person("xl");   
       5     console.log(personA.name); // 輸出  undefined
       6     console.log(window.name);//輸出  xl
       7     //上面代碼沒有進行new操作,相當于window對象調用Person("xl")方法,那么this指向window對象,并進行賦值操作window.name="xl".
       8     
       9     var personB=new Person("xl");
      10     console.log(personB.name);// 輸出 xl
      11     //這部分代碼的解釋見下

       

      new操作符

        //下面這段代碼模擬了new操作符(實例化對象)的內部過程
          function person(name){
              var o={};
              o.__proto__=Person.prototype;  //原型繼承
              Person.call(o,name);
              return o;
          }
          var personB=person("xl");
          
          console.log(personB.name);  // 輸出  xl
          

           這段代碼涉及到了_proto_及prototype的概念,如果有需要了解,請點擊鏈接

      • person里面首先創建一個空對象o,將o的proto指向Person.prototype完成對原型的屬性和方法的繼承

      • Person.call(o,name)這里即函數Person作為apply/call調用(具體內容下方),將Person對象里的this改為o,即完成了o.name=name操作

      • 返回對象o。

        因此`person("xl")`返回了一個繼承了`Person.prototype`對象上的屬性和方法,以及擁有`name`屬性為"xl"的對象,并將它賦給變量`personB`.
        所以`console.log(personB.name)`會輸出"xl"
        

      call/apply方法的調用

      在JS里函數也是對象,因此函數也有方法。從Function.prototype上繼承到Function.prototype.call/Function.prototype.apply方法
      call/apply方法最大的作用就是能改變this關鍵字的指向.

      Obj.method.apply(AnotherObj,arguments);

       1     var name="XL";
       2     var Person={
       3         name:"xl",
       4         showName:function(){
       5             console.log(this.name);
       6         }
       7     }
       8     Person.showName.call(); //輸出 "XL"
       9     //這里call方法里面的第一個參數為空,默認指向window。
      10     //雖然showName方法定義在Person對象里面,但是使用call方法后,將showName方法里面的this指向了window。因此最后會輸出"XL";
      11     funtion FruitA(n1,n2){
      12         this.n1=n1;
      13         this.n2=n2;
      14         this.change=function(x,y){
      15             this.n1=x;
      16             this.n2=y;
      17         }
      18     }
      19     
      20     var fruitA=new FruitA("cheery","banana");
      21     var FruitB={
      22         n1:"apple",
      23         n2:"orange"
      24     };
      25     fruitA.change.call(FruitB,"pear","peach");
      26     
      27     console.log(FruitB.n1); //輸出 pear
      28     console.log(FruitB.n2);// 輸出 peach

       

      FruitB調用fruitAchange方法,將fruitA中的this綁定到對象FruitB上。

      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綁定到當前作用域的對象上

          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

       參考資料

      posted on 2016-07-19 15:08  沙沙起  閱讀(25990)  評論(7)    收藏  舉報
       
      主站蜘蛛池模板: 亚洲国产良家在线观看| 《特殊的精油按摩》3| 亚洲五月丁香综合视频| 久久精品国产99久久六动漫| 亚洲男人在线天堂| 又黄又爽又色的免费网站| 日本一区二区久久人妻高清| 中文字幕日韩精品人妻| 国产日韩一区二区四季| 久久久久香蕉国产线看观看伊 | 亚洲国产色婷婷久久99精品91| 中文字幕一区二区久久综合| 中文字幕日韩精品亚洲一区| 国产精品自在自线视频| 国产久9视频这里只有精品| 内射一区二区三区四区| 日韩黄色av一区二区三区| 伊人久久大香线蕉AV网| 亚洲精品国精品久久99热| 亚洲国产成人无码电影| 最新的国产成人精品2020| 高清不卡一区二区三区| 成人欧美一区在线视频| 国模少妇无码一区二区三区| 亚洲熟妇中文字幕五十路| 亚洲av午夜成人片| 日本欧美一区二区三区在线播放 | 无码囯产精品一区二区免费| 亚洲人妻系列中文字幕| 日韩精品人妻av一区二区三区| 精品无码国产一区二区三区AV| 亚洲国产在一区二区三区| www久久只有这里有精品| 久久精品国产最新地址| 亚洲成a人片在线视频| 国产精品普通话国语对白露脸 | 精品人妻av综合一区二区| 艳妇乳肉豪妇荡乳xxx| 精品av综合导航| 女高中生强奷系列在线播放 | 精品亚洲一区二区三区在线观看|