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

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

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

      詳解javascript立即執(zhí)行函數(shù)表達式(IIFE)

      立即執(zhí)行函數(shù),就是在定義函數(shù)的時候直接執(zhí)行,這里不是申明函數(shù)而是一個函數(shù)表達式

      1.問題

      在javascript中,每一個函數(shù)在被調(diào)用的時候都會創(chuàng)建一個執(zhí)行上下文,在函數(shù)內(nèi)部定義的變量和函數(shù)只能在該函數(shù)內(nèi)部調(diào)用,正是因為這個上下文,使得在調(diào)用函數(shù)的時候可以創(chuàng)建一些私有變量。如下代碼

          //makeCounter,返回一個新的函數(shù)(閉包),這個函數(shù)可以訪問makeCounter里的局部變量i
          function makeCounter() {
            var i = 0;
            return function () {
              document.write(++i);
              document.write('<br>');
            }
          }
      
          //counter1和counter2是不同的實例,分別擁有自己范圍內(nèi)的變量i
          var counter1 = makeCounter();
          counter1();
          counter1();
      
          var counter2 = makeCounter();
          counter2();
          counter2();

      這里i是函數(shù)makeCounter函數(shù)內(nèi)的局部變量,所以定義的counter1和counter2都有自己的變量i,上面代碼輸出結(jié)果如下:

      注意閉i始終保存在內(nèi)存中,所以第二次調(diào)用的時候輸出的是2。

      普通情況下我們定義一個函數(shù),然后在語句中函數(shù)名字后面加上一對圓括號就可以直接調(diào)用它,能不能定義完之后直接在后面加上小括號調(diào)用呢?如下

      function(){ counter1(); }(); // SyntaxError: Unexpected token (

      答案是不行,這樣會報錯的。為什么呢?在javascript解釋代碼的時候,遇到function關鍵字的時候就認為這里是一個函數(shù)聲明而不是函數(shù)表達式,如果沒有顯式地定義成函數(shù)表達式就會報錯,因為函數(shù)聲明需要一個函數(shù)名,上面的代碼沒有函數(shù)名。

      既然是因為沒有函數(shù)名字報錯那好就加上一個函數(shù)名,如下:

      function foo(){ counter1(); }(); // SyntaxError: Unexpected token )

      依然會報錯,為什么呢?在一個函數(shù)聲明語句(這次是正確的)后面加上一對圓括號,這對圓括號和前面的聲明語句沒有任關系,而只是一個分組操作符,用來控制運算的優(yōu)先級,這里的意思是小括號里面優(yōu)先計算,所以上面代碼等同于:

      function foo(){ counter1(); }
      (); // SyntaxError: Unexpected token )

       

      2.概念

      正確的寫法是怎樣的呢?簡單,如下:

      (function () { counter1(); }());

      這樣為什么就可以呢?在javascript里圓括號內(nèi)不能包含語句,當解釋器對代碼進行解釋的時候遇到圓括號就認為這里面是表達式,然后遇到function關鍵字就認為這是一個函數(shù)表達式,而不是函數(shù)聲明。而更加奇妙的是只要是能將后面語句預先解釋為表達式都可以,不一定是分分組操作符,于是立即執(zhí)行函數(shù)表達式有了五花八門的寫法,如下:

          (function () { counter1(); }());
          (function () { counter1(); })();
          var i = function(){ counter1(); }();
          true && function () { counter1(); }();
          0, function(){ counter1() }();
          !function () { counter1(); }();
          ~function () { counter1(); }();
          -function () { counter1(); }();
          +function () { counter1(); }();

      輸出結(jié)果如下:

      甚至可以這樣:

          new function(){ counter1(); }
          new function(){ counter1(); }() // 帶參數(shù)

      這樣:

      var i = function(){ counter1(); }();
      var j = (function(){ return 10; }());

      這是為什么呢?因為new,=是運算符,和+,-,*,/一個樣,都會把后面的語句預先解釋為表達式。這里推薦上面一種寫法,因為function內(nèi)部代碼如果太多,我們不得不滾到最后去看function(){}后是否帶有()。

       

      3.立即執(zhí)行函數(shù)和閉包有什么關系

       和普通函數(shù)傳參一樣,立即執(zhí)行函數(shù)也可以傳遞參數(shù)。如果在函數(shù)內(nèi)部定一個函數(shù),而里面的那個函數(shù)能引用外部的變量和參數(shù)(閉包),我們就能用立即執(zhí)行函數(shù)鎖定變量保存狀態(tài)。

      我們在hmtl頁面中方兩個超鏈接標簽,然后用下面的代碼來測試:

      <div>
          <ul>
              <li><a>第一個超鏈接</a></li>
              <li><a>第二個超鏈接</a></li>
          </ul>
      </div>
          var elems = document.getElementsByTagName('a');
          for(var i=0; i<elems.length; i++) {
            elems[i].addEventListener('click', function (e) {
              e.preventDefault();
              alert('I am click Link #' + i);
            }, 'false')
          }

      這段代碼意圖是點擊第一個超鏈接提示“I am click Link #0”,點擊第二個提示“I am click Link #1”。真的是這樣嗎? 不是,每一次都是“I am click Link #2”

      因為i的值沒有被鎖住,當我們點擊鏈接的時候其實for循環(huán)早已經(jīng)執(zhí)行完了,于是在點擊的時候i的值已經(jīng)是elems.length了。

      修改代碼如下:

          var elems = document.getElementsByTagName('a');
          for(var i=0; i < elems.length; i++){
            (function (LockedInIndex) {
              elems[i].addEventListener('click', function (e) {
                e.preventDefault();
                alert('I am cliick Link #' + i);
              }, 'false')
            })(i)
          } 

      這次可以正確的輸出結(jié)果,i的值被傳給了LockedIndex,并且被鎖定在內(nèi)存中,盡管for循環(huán)之后i的值已經(jīng)改變,但是立即執(zhí)行函數(shù)內(nèi)部的LockedIndex的值并不會改變。

      還可以這樣寫:

          var elems = document.getElementsByTagName('a');
          for ( var i = 0; i < elems.length; i++ ) {
            elems[ i ].addEventListener( 'click', (function( lockedInIndex ){
              return function(e){
                e.preventDefault();
                alert( 'I am link #' + lockedInIndex );
              };
            })( i ), 'false' );
          }

      但是我覺得如果用let是不是就可以一下子解決了:

         var elems = document.getElementsByTagName('a');
          for(let i=0; i<elems.length; i++) {
            elems[i].addEventListener('click', function (e) {
              e.preventDefault();
              alert('I am click Link #' + i);
            }, 'false')
          }

      let是塊級作用域內(nèi)的變量,是es6新定義的,這里不展開。

      4.模塊模式

      立即執(zhí)行函數(shù)在模塊化的時候也有用,用立即執(zhí)行函數(shù)處理模塊可以減少全局變量造成的空間污染,而是使用私有變量。

      如下創(chuàng)建一個立即執(zhí)行的匿名函數(shù),該函數(shù)返回一個對象,包含要暴露給外部的屬性i,如果不實用立即執(zhí)行函數(shù)就要多定義一個屬性i了,這個i就會顯示的暴露給外部,這樣:counter.i,這種方式明顯不太安全。

          var counter = (function(){
            var i = 0;
      
            return {
              get: function(){
                return i;
              },
              set: function( val ){
                i = val;
              },
              increment: function() {
                return ++i;
              }
            };
          }());
          document.write('<br>');
          document.write(counter.get());document.write('<br>');
          document.write(counter.set( 3 ));document.write('<br>');
          document.write(counter.increment());document.write('<br>'); // 4
          document.write(counter.increment());document.write('<br>'); // 5

      注意,這里如果使用counter.i來訪問這個內(nèi)部變量,會報錯undefined,因為i并不是counter的屬性。

      好了,就這么多。

       

      posted @ 2017-03-21 20:46  nd  閱讀(3998)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产色视频一区二区三区qq号 | 亚洲人妻精品中文字幕| 五月综合激情婷婷六月色窝| 亚洲一区二区三区18禁| 欧美18videosex性欧美tube1080| 国产午夜精品理论大片| 亚洲第一成年免费网站| 国产精品激情av在线播放| 亚洲欧美人成网站在线观看看| 国产精品第二页在线播放| 日本一区二区不卡精品| 国产永久免费高清在线| 亚洲欧美综合精品成人网站| 97免费在线观看视频| 亚洲男人av天堂久久资源| 久久久久成人精品免费播放动漫| 久热这里只有精品视频3| 国产成人精品一区二区三区| 亚洲欧洲一区二区综合精品 | 亚洲人成网站在线播放2019| 亚洲色欲在线播放一区二区三区| 国产成人精品一区二区三区无码| 男女做aj视频免费的网站| 国产精品自在拍首页视频8| 南漳县| 国产一区二区av天堂热| 国内揄拍国内精品人妻| 闻喜县| 亚洲全网成人资源在线观看| 人人妻人人澡人人爽欧美一区双| 亚洲狠狠婷婷综合久久久| 波多野42部无码喷潮| 亚洲综合欧美在线…| 精品一区二区亚洲国产| 新野县| 啪啪av一区二区三区| 四虎成人精品无码| 国产精品无码无片在线观看3d| 99久久婷婷国产综合精品青草漫画 | 91久久精品美女高潮不断| 亚洲av成人在线一区|