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

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

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

      【javascript】函數中的this的四種綁定形式 — 大家準備好瓜子,我要講故事啦~~

       
       javascript中的this和函數息息相關,所以今天,我就給大家詳細地講述一番:javascript函數中的this
       
      一談到this,很多讓人暈暈乎乎的抽象概念就跑出來了,這里我就只說最核心的一點——函數中的this總指向調用它的對象,接下來的故事都將圍繞這一點展開
       
      (提醒前排的筒子們準備好茶水和西瓜,我要開始講故事啦!!)
       
       
      【故事】有一個年輕人叫"迪斯"(this),有一天,迪斯不小心穿越到一個叫 “伽瓦斯克利”(javascript)的 異世界,此時此刻迪斯身無分文, 他首先要做的事情就是——找到他的住宿的地方——調用函數的對象
       

       

      this的默認綁定

       

      【故事——線路1】如果迪斯(this)直到天黑前都沒有找到能收留自己的住所,他眼看就要過上非洲難民的生活, 這時候,一位樂善好施的魔法師村長——window救世主一般地出現了:先住在我家吧!
       

       

      【正文】
      當一個函數沒有明確的調用對象的時候,也就是單純作為獨立函數調用的時候,將對函數的this使用默認綁定:綁定到全局的window對象
      function fire () {
           console.log(this === window)
      }
      fire(); // 輸出true

       

      上面的例子我相信對大多數人都很簡單,但有的時候我們把例子變一下就會具有迷惑性:
      function fire () {
        // 我是被定義在函數內部的函數哦!
           function innerFire() {
        console.log(this === window)
            }
           innerFire(); // 獨立函數調用
      }
      fire(); // 輸出true

       

       
      函數 innerFire在一個外部函數fire里面聲明且調用,那么它的this是指向誰呢? 仍然是window
       
      許多人可能會顧慮于fire函數的作用域對innerFire的影響,但我們只要抓住我們的理論武器——沒有明確的調用對象的時候,將對函數的this使用默認綁定:綁定到全局的window對象,便可得正確的答案了
       
      下面這個加強版的例子也是同樣的輸出true
      var obj = {
         fire: function () {
             function innerFire() {
                console.log(this === window)
              }
              innerFire();   // 獨立函數調用
           }
      }
      obj.fire(); //輸出 true

       

      【注意】在這個例子中, obj.fire()的調用實際上使用到了this的隱式綁定,這就是下面我要講的內容,這個例子我接下來還會繼續講解
       
      【總結】 凡事函數作為獨立函數調用,無論它的位置在哪里,它的行為表現,都和直接在全局環境中調用無異
       

      this的隱式綁定

      【故事——線路2】 迪斯(this)穿越來異世界“伽瓦斯克利”(javascript)的時候,剛好身上帶了一些錢,于是他找到一個旅館住宿了下來
       
       
       

       

      當函數被一個對象“包含”的時候,我們稱函數的this被隱式綁定到這個對象里面了,這時候,通過this可以直接訪問所綁定的對象里面的其他屬性,比如下面的a屬性
       
      var obj = {
           a: 1,
            fire: function () {
                 console.log(this.a)
              }
      }
      obj.fire(); // 輸出1

       

       
      現在我們需要對平常司空見慣的的代碼操作做一些更深的思考,首先,下面的這兩段代碼達到的效果是相同的:
      // 我是第一段代碼
      function fire () {
            console.log(this.a)
      }
        
      var obj = {
            a: 1,
            fire: fire
        }
      obj.fire(); // 輸出1
       
      // 我是第二段代碼
      var obj = {
              a: 1,
              fire: function () {
                   console.log(this.a)
               }
      }
      obj.fire(); // 輸出1

       

       
      fire函數并不會因為它被定義在obj對象的內部和外部而有任何區別,也就是說在上述隱式綁定的兩種形式下,fire通過this還是可以訪問到obj內的a屬性,這告訴我們:
       
      1.  this是動態綁定的,或者說是在代碼運行期綁定而不是在書寫期
      2.  函數于對象的獨立性, this的傳遞丟失問題
       
      (下面的描述可能帶有個人的情感傾向而顯得不太嚴謹,但這是因為我希望閱讀者盡可能地理解我想表達的意思)

      隱式綁定下,作為對象屬性的函數,對于對象來說是獨立的

       
      基于this動態綁定的特點,寫在對象內部,作為對象屬性的函數,對于這個對象來說是獨立的。(函數并不被這個外部對象所完全擁有”)
       
      我想表達的意思是:在上文中,函數雖然被定義在對象的內部中,但它和“在對象外部聲明函數,然后在對象內部通過屬性名稱的方式取得函數的引用”,這兩種方式在性質上是等價的而不僅僅是效果上
       
      定義在對象內部的函數只是“恰好可以被這個對象調用”而已,而不是“生來就是為這個對象所調用的”
       
      借用下面的隱式綁定中的this傳遞丟失問題來說明:
      var obj = {
            a: 1,    // a是定義在對象obj中的屬性   1
            fire: function () {
         console.log(this.a)
              }
            }
       
      var a = 2// a是定義在全局環境中的變量    2
      var fireInGrobal = obj.fire;  
      fireInGrobal(); //  輸出 2

       

       
      上面這段簡單代碼的有趣之處在于: 這個于obj中的fire函數的引用( fireInGrobal)在調用的時候,行為表現(輸出)完全看不出來它就是在obj內部定義的其原因在于:我們隱式綁定的this丟失了!! 從而 fireInGrobal調用的時候取得的this不是obj,而是window
       
      上面的例子稍微變個形式就會變成一個可能困擾我們的bug:
       
      var a = 2;
      var obj = {
          a: 1,    // a是定義在對象obj中的屬性
          fire: function () {
                console.log(this.a)
           }
      }  
      function otherFire (fn) {
           fn();
      }  
      otherFire(obj.fire); // 輸出2

       

       
      在上面,我們的關鍵角色是otherFire函數,它接受一個函數引用作為參數,然后在內部直接調用,但它做的假設是參數fn仍然能夠通過this去取得obj內部的a屬性,但實際上, this對obj的綁定早已經丟失了,所以輸出的是全局的a的值(2),而不是obj內部的a的值(1)
       

      在一串對象屬性鏈中,this綁定的是最內層的對象

      在隱式綁定中,如果函數調用位置是在一串對象屬性鏈中,this綁定的是最內層的對象。如下所示:
      var obj = {
            a: 1,
            obj2: {
                 a: 2,
                 obj3: {
                      a:3,
                      getA: function () {
                          console.log(this.a)   
                       }
                 }
             }
      }
       
      obj.obj2.obj3.getA();  // 輸出3

       

       

      this的顯式綁定:(call和bind方法)

      【故事——線路3】 迪斯(this)穿越來異世界“伽瓦斯克利”(javascript),經過努力的打拼,積累了一定的財富,于是他買下了自己的房子
       

       

      上面我們提到了this的隱式綁定所存在的this綁定丟失的問題,也就是對于 “ fireInGrobal = obj.fire”
      fireInGrobal調用和obj.fire調用的結果是不同的因為這個函數賦值的過程無法把fire所綁定的this也傳遞過去。這個時候,call函數就派上用場了

       

      call的基本使用方式: fn.call(object)
      fn是你調用的函數,object參數是你希望函數的this所綁定的對象。
      fn.call(object)的作用:
      1.即刻調用這個函數(fn)
      2.調用這個函數的時候函數的this指向object對象
       
      例子:
      var obj = {
            a: 1,    // a是定義在對象obj中的屬性
            fire: function () {
               console.log(this.a)
            }
      }
       
      var a = 2// a是定義在全局環境中的變量  
      var fireInGrobal = obj.fire;
      fireInGrobal();   // 輸出2
      fireInGrobal.call(obj); // 輸出1

       

       
      原本丟失了與obj綁定的this參數的fireInGrobal再次重新把this綁回到了obj
       
      但是,我們其實不太喜歡這種每次調用都要依賴call的方式,我們更希望:能夠一次性 返回一個this被永久綁定到obj的fireInGrobal函數,這樣我們就不必每次調用fireInGrobal都要在尾巴上加上call那么麻煩了。
       
      怎么辦呢? 聰明的你一定能想到,在fireInGrobal.call(obj)外面包裝一個函數不就可以了嘛!
      var obj = {
            a: 1,    // a是定義在對象obj中的屬性
            fire: function () {
              console.log(this.a)
            }
      }
       
      var a = 2// a是定義在全局環境中的變量  
      var fn = obj.fire;
      var fireInGrobal = function () {
          fn.call(obj)   //硬綁定
      }
             
      fireInGrobal(); // 輸出1

       

      如果使用bind的話會更加簡單
      var fireInGrobal = function () {
          fn.call(obj)   //硬綁定
      }

       

      可以簡化為:
      var fireInGrobal = fn.bind(obj);

       

      call和bind的區別是:在綁定this到對象參數的同時:
       
      1.call將立即執行該函數
      2.bind不執行函數,只返回一個可供執行的函數
       
      【其他】:至于apply,因為除了使用方法,它和call并沒有太大差別,這里不加贅述
       
      在這里,我把顯式綁定和隱式綁定下,函數和“包含”函數的對象間的關系比作買房和租房的區別
       

       

      因為this的緣故
       
      在隱式綁定下:函數和只是暫時住在“包含對象“的旅館里面,可能過幾天就又到另一家旅館住了
      在顯式綁定下:函數將取得在“包含對象“里的永久居住權,一直都會”住在這里“
       

      new綁定

      【故事】 迪斯(this)組建了自己的家庭,并生下多個孩子(通過構造函數new了許多個對象)
       
       

       

      執行new操作的時候,將創建一個新的對象,并且將構造函數的this指向所創建的新對象
       
      function foo (a) {
           this.a = a;
      }
       
      var a1  = new foo (1);
      var a2  = new foo (2);
      var a3  = new foo (3);
      var a4  = new foo (4);
       
      console.log(a1.a); // 輸出1
      console.log(a2.a); // 輸出2
      console.log(a3.a); // 輸出3
      console.log(a4.a); // 輸出4

       

       
      謝謝大家哦!!
       
      【完】
       

       

      posted @ 2017-08-14 09:53  外婆的  閱讀(23089)  評論(93)    收藏  舉報
      主站蜘蛛池模板: 亚洲制服无码一区二区三区 | 国产成人精品久久一区二区| 久久亚洲精品情侣| 野外做受又硬又粗又大视频√| 亚洲综合在线亚洲优优色| 久久综合香蕉国产蜜臀av| 又大又粗又爽的少妇免费视频 | 欧美精品一区二区在线观看播放| 久久天天躁狠狠躁夜夜网站| 亚洲成av人片无码迅雷下载| 给我中国免费播放片在线| 中国女人熟毛茸茸A毛片| 久久综合狠狠综合久久激情| 亚洲人成网站77777在线观看| 焦作市| 熟女一区| 两性午夜刺激性视频| 色综合久久婷婷88| 绵竹市| 一本一道av无码中文字幕麻豆| 精品日韩亚洲av无码| 国产精品香蕉在线观看不卡| 美女一区二区三区在线观看视频| 超碰人人超碰人人| 免费黄色大全一区二区三区| 大香伊蕉在人线国产免费| 久久精品不卡一区二区| 日韩av在线一卡二卡三卡| 精品一区二区av天堂| 色翁荡息又大又硬又粗又视频图片 | 国产综合av一区二区三区| 亚洲国产成人AⅤ片在线观看| 国产在线98福利播放视频| 精品黄色av一区二区三区| 中文字幕亚洲综合久久| 亚洲男人天堂东京热加勒比| 噜噜久久噜噜久久鬼88| 99久久婷婷国产综合精品青草漫画| 国产精品国产三级国av| 亚洲精品一区久久久久一品av | 一区二区视频观看在线|