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

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

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

      深入理解this機制系列第一篇——this的4種綁定規(guī)則

      前面的話

        如果要問javascript中哪兩個知識點容易混淆,作用域查詢和this機制絕對名列前茅。前面的作用域系列已經(jīng)詳細(xì)介紹過作用域的知識。本系列開始將介紹javascript的另一大山脈——this機制。本文是該系列的第一篇——this的4種綁定規(guī)則

       

      默認(rèn)綁定

        全局環(huán)境中,this默認(rèn)綁定到window

      console.log(this === window);//true

        函數(shù)獨立調(diào)用時,this默認(rèn)綁定到window

      function foo(){
          console.log(this === window);
      }
      foo(); //true

        被嵌套的函數(shù)獨立調(diào)用時,this默認(rèn)綁定到window

      //雖然test()函數(shù)被嵌套在obj.foo()函數(shù)中,但test()函數(shù)是獨立調(diào)用,而不是方法調(diào)用。所以this默認(rèn)綁定到window
      var a = 0;
      var obj = {
          a : 2,
          foo:function(){
                  function test(){
                      console.log(this.a);
                  }
                  test();
          }
      }
      obj.foo();//0

      【IIFE】

        IIFE立即執(zhí)行函數(shù)實際上是函數(shù)聲明后直接調(diào)用執(zhí)行

      var a = 0;
      function foo(){
          (function test(){
              console.log(this.a);
          })()
      };
      var obj = {
          a : 2,
          foo:foo
      }
      obj.foo();//0
      //等價于上例
      var a = 0;
      var obj = {
          a : 2,
          foo:function(){
                  function test(){
                      console.log(this.a);
                  }
                  test();
          }
      }
      obj.foo();//0

      【閉包】

        類似地,test()函數(shù)是獨立調(diào)用,而不是方法調(diào)用,所以this默認(rèn)綁定到window

        [注意]函數(shù)共有4種調(diào)用方式,函數(shù)調(diào)用相關(guān)內(nèi)容移步至此

      var a = 0;
      function foo(){
          function test(){
              console.log(this.a);
          }
          return test;
      };
      var obj = {
          a : 2,
          foo:foo
      }
      obj.foo()();//0

        由于閉包的this默認(rèn)綁定到window對象,但又常常需要訪問嵌套函數(shù)的this,所以常常在嵌套函數(shù)中使用var that = this,然后在閉包中使用that替代this,使用作用域查找的方法來找到嵌套函數(shù)的this值 

      var a = 0;
      function foo(){
          var that = this;
          function test(){
              console.log(that.a);
          }
          return test;
      };
      var obj = {
          a : 2,
          foo:foo
      }
      obj.foo()();//2

       

      隱式綁定

        一般地,被直接對象所包含的函數(shù)調(diào)用時,也稱為方法調(diào)用,this隱式綁定到該直接對象

      function foo(){
          console.log(this.a);
      };
      var obj1 = {
          a:1,
          foo:foo,
          obj2:{
              a:2,
              foo:foo
          }
      }
      
      //foo()函數(shù)的直接對象是obj1,this隱式綁定到obj1
      obj1.foo();//1
      
      //foo()函數(shù)的直接對象是obj2,this隱式綁定到obj2
      obj1.obj2.foo();//2

       

      隱式丟失

        隱式丟失是指被隱式綁定的函數(shù)丟失綁定對象,從而默認(rèn)綁定到window。這種情況容易出錯卻又常見

      【函數(shù)別名】

      var a = 0;
      function foo(){
          console.log(this.a);
      };
      var obj = {
          a : 2,
          foo:foo
      }
      //把obj.foo賦予別名bar,造成了隱式丟失,因為只是把foo()函數(shù)賦給了bar,而bar與obj對象則毫無關(guān)系
      var bar = obj.foo;
      bar();//0
      //等價于
      var a = 0;
      var bar = function foo(){
          console.log(this.a);
      }
      bar();//0

      【參數(shù)傳遞】

      var a = 0;
      function foo(){
          console.log(this.a);
      };
      function bar(fn){
          fn();
      }
      var obj = {
          a : 2,
          foo:foo
      }
      //把obj.foo當(dāng)作參數(shù)傳遞給bar函數(shù)時,有隱式的函數(shù)賦值fn=obj.foo。與上例類似,只是把foo函數(shù)賦給了fn,而fn與obj對象則毫無關(guān)系
      bar(obj.foo);//0
      //等價于
      var a = 0;
      function bar(fn){
          fn();
      }
      bar(function foo(){
          console.log(this.a);
      });

      【內(nèi)置函數(shù)】

        內(nèi)置函數(shù)與上例類似,也會造成隱式丟失

      var a = 0;
      function foo(){
          console.log(this.a);
      };
      var obj = {
          a : 2,
          foo:foo
      }
      setTimeout(obj.foo,100);//0
      //等價于
      var a = 0;
      setTimeout(function foo(){
          console.log(this.a);
      },100);//0

      【間接引用】

         函數(shù)的"間接引用"一般都在無意間創(chuàng)建,最容易在賦值時發(fā)生,會造成隱式丟失

      function foo() {
          console.log( this.a );
      }
      var a = 2;
      var o = { a: 3, foo: foo };
      var p = { a: 4 };
      o.foo(); // 3
      //將o.foo函數(shù)賦值給p.foo函數(shù),然后立即執(zhí)行。相當(dāng)于僅僅是foo()函數(shù)的立即執(zhí)行
      (p.foo = o.foo)(); // 2
      function foo() {
          console.log( this.a );
      }
      var a = 2;
      var o = { a: 3, foo: foo };
      var p = { a: 4 };
      o.foo(); // 3
      //將o.foo函數(shù)賦值給p.foo函數(shù),之后p.foo函數(shù)再執(zhí)行,是屬于p對象的foo函數(shù)的執(zhí)行
      p.foo = o.foo;
      p.foo();//4

       【其他情況】

        在javascript引擎內(nèi)部,obj和obj.foo儲存在兩個內(nèi)存地址,簡稱為M1和M2。只有obj.foo()這樣調(diào)用時,是從M1調(diào)用M2,因此this指向obj。但是,下面三種情況,都是直接取出M2進(jìn)行運算,然后就在全局環(huán)境執(zhí)行運算結(jié)果(還是M2),因此this指向全局環(huán)境

      var a = 0;
      var obj = {
          a : 2,
          foo:foo
      };
      function foo() {
          console.log( this.a );
      };
      
      (obj.foo = obj.foo)();//0
      
      (false || obj.foo)();//0
      
      (1, obj.foo)();//0

       

      顯式綁定

        通過call()、apply()、bind()方法把對象綁定到this上,叫做顯式綁定。對于被調(diào)用的函數(shù)來說,叫做間接調(diào)用

      var a = 0;
      function foo(){
          console.log(this.a);
      }
      var obj = {
          a:2
      };
      foo();//0
      foo.call(obj);//2

        普通的顯式綁定無法解決隱式丟失問題

      var a = 0;
      function foo(){
          console.log(this.a);
      }
      var obj1 = {
          a:1
      };
      var obj2 = {
          a:2
      };
      foo.call(obj1);//1
      foo.call(obj2);//2

      【硬綁定】

        硬綁定是顯式綁定的一個變種,使this不能再被修改

      var a = 0;
      function foo(){
          console.log(this.a);
      }
      var obj = {
          a:2
      };
      var bar= function(){
          foo.call(obj);
      }
      //在bar函數(shù)內(nèi)部手動調(diào)用foo.call(obj)。因此,無論之后如何調(diào)用函數(shù)bar,它總會手動在obj上調(diào)用foo
      bar();//2
      setTimeout(bar,100);//2
      bar.call(window);//2

      【API】

        javascript中新增了許多內(nèi)置函數(shù),具有顯式綁定的功能,如數(shù)組的5個迭代方法:map()、forEach()、filter()、some()、every()

      var id = 'window';
      function foo(el){
          console.log(el,this.id);
      }
      var obj = {
          id: 'fn'
      };
      [1,2,3].forEach(foo);//1 "window" 2 "window" 3 "window"
      [1,2,3].forEach(foo,obj);//1 "fn" 2 "fn" 3 "fn"

       

      new綁定

        如果函數(shù)或者方法調(diào)用之前帶有關(guān)鍵字new,它就構(gòu)成構(gòu)造函數(shù)調(diào)用。對于this綁定來說,稱為new綁定

        【1】構(gòu)造函數(shù)通常不使用return關(guān)鍵字,它們通常初始化新對象,當(dāng)構(gòu)造函數(shù)的函數(shù)體執(zhí)行完畢時,它會顯式返回。在這種情況下,構(gòu)造函數(shù)調(diào)用表達(dá)式的計算結(jié)果就是這個新對象的值

      function fn(){
          this.a = 2;
      }
      var test = new fn();
      console.log(test);//{a:2}

        【2】如果構(gòu)造函數(shù)使用return語句但沒有指定返回值,或者返回一個原始值,那么這時將忽略返回值,同時使用這個新對象作為調(diào)用結(jié)果

      function fn(){
          this.a = 2;
          return;
      }
      var test = new fn();
      console.log(test);//{a:2}

        【3】如果構(gòu)造函數(shù)顯式地使用return語句返回一個對象,那么調(diào)用表達(dá)式的值就是這個對象

      var obj = {a:1};
      function fn(){
          this.a = 2;
          return obj;
      }
      var test = new fn();
      console.log(test);//{a:1}

        [注意]盡管有時候構(gòu)造函數(shù)看起來像一個方法調(diào)用,它依然會使用這個新對象作為this。也就是說,在表達(dá)式new o.m()中,this并不是o

      var o = {
          m: function(){
              return this;
          }
      }
      var obj = new o.m();
      console.log(obj,obj === o);//{} false
      console.log(obj.constructor === o.m);//true

       

      嚴(yán)格模式

        【1】嚴(yán)格模式下,獨立調(diào)用的函數(shù)的this指向undefined

      function fn(){
          'use strict';
          console.log(this);//undefined
      }
      fn();
      
      function fn(){
          console.log(this);//window
      }
      fn();

        【2】在非嚴(yán)格模式下,使用函數(shù)的call()或apply()方法時,null或undefined值會被轉(zhuǎn)換為全局對象。而在嚴(yán)格模式下,函數(shù)的this值始終是指定的值

      var color = 'red';
      function displayColor(){
          console.log(this.color);
      }
      displayColor.call(null);//red
      
      var color = 'red';
      function displayColor(){
          'use strict';
          console.log(this.color);
      }
      displayColor.call(null);//TypeError: Cannot read property 'color' of null

       

      最后

        this的四種綁定規(guī)則:默認(rèn)綁定、隱式綁定、顯式綁定和new綁定,分別對應(yīng)函數(shù)的四種調(diào)用方式:獨立調(diào)用、方法調(diào)用、間接調(diào)用和構(gòu)造函數(shù)調(diào)用。

        分清這四種綁定規(guī)則不算難,比較麻煩的是需要練就火眼金睛,識別出隱式丟失的情況

        說到底,javascript如此復(fù)雜的原因是因為函數(shù)過于強大。因為,函數(shù)是對象,所以原型鏈比較復(fù)雜;因為函數(shù)可以作為值被傳遞,所以執(zhí)行環(huán)境棧比較復(fù)雜;同樣地,因為函數(shù)具有多種調(diào)用方式,所以this的綁定規(guī)則也比較復(fù)雜

        只有理解了函數(shù),才算理解了javascript

        以上

      posted @ 2016-08-04 12:40  小火柴的藍(lán)色理想  閱讀(12238)  評論(6)    收藏  舉報
      主站蜘蛛池模板: 理论片午午伦夜理片久久| 日韩伦人妻无码| 亚洲一区二区三区 无码| 老熟女重囗味hdxx69| 久久夜色国产噜噜亚洲av| 欧美色欧美亚洲高清在线观看| 香蕉久久久久久久av网站| 国产一级精品在线免费看| 国产私拍大尺度在线视频| 色老99久久九九爱精品| 少妇人妻真实偷人精品| 欧美日韩国产码高清| 成人区人妻精品一区二区| 成年在线观看免费人视频 | 午夜在线欧美蜜桃| 日韩欧激情一区二区三区| 中文一区二区视频| 亚洲a免费| 十八禁国产一区二区三区| 日本一卡二卡不卡视频查询| 亚洲精品乱码免费精品乱| 青青国产揄拍视频| 国产真实野战在线视频| 日韩一区二区三在线观看| 日本一道一区二区视频| 少妇人妻偷人免费观看| 黄色舔女人逼一区二区三区| 国产综合久久99久久| 国产仑乱无码内谢| 中文字日产幕码三区国产| 在线观看潮喷失禁大喷水无码| 国产精品 无码专区| a级国产乱理伦片在线观看al| 粗大猛烈进出高潮视频| 青青草原网站在线观看| 四川少妇被弄到高潮| 欧美视频二区欧美影视| 色综合久久中文综合久久激情 | 激情综合网激情五月激情 | 国产91精品调教在线播放| 99网友自拍视频在线|