Javascript的匿名函數與自執行

來源:互聯網
上載者:User

標籤:

本文和大家分享的主要是javascript 中的匿名函數與自執行相關內容,一起來看看吧,希望對大家 學習javascript有所協助。函數是JavaScript 中最靈活的一種對象,這裡只是講解其匿名函數的用途。匿名函數:就是沒有函數名的函數 函數分幾種函數的定義,大致可分為三種方式:第一種:這也是最常規的一種 function  double(x){ return 2 * x;}第二種:這種方法使用了Function 建構函式,把參數列表和函數體都作為字串,很不方便,不建議使用 var double =  new  Function(’x’, ’return 2 * x;’);第三種: var double =  function(x) {  return 2* x; }注意“=” 右邊的函數就是一個匿名函數,創造完畢函數後,又將該函數賦給了變數 double 匿名函數的建立第一種方式:就是上面所講的定義double 函數,這也是最常用的方式之一第二種方式:( function( x, y){alert( x + y);})(2, 3);這裡建立了一個匿名函數( 在第一個括弧內 ) ,第二個括弧用於調用該匿名函數,並傳入參數。括弧是運算式,是運算式就有傳回值,所以可以在後面加一對括弧讓它們執行 var a = 1;   var b = 2;( function(){var b = 3;a += b;})();alert(a); // 4alert(b); // 2 自執行的匿名函數 自執行的匿名函數是指形如這樣的函數:( function {// code})(); 為什麼 (function {// code})(); 可以被執行, 而 function {// code}(); 卻會報錯?1.首先,  要清楚兩者的區別 :  (function {// code})  是運算式,  function {// code}  是函式宣告.2.3.其次, js" 先行編譯 " 的特點 :js 在 " 先行編譯 " 階段 ,  會解釋函式宣告 ,  但卻會忽略表式 .4.5.當js 執行到  function() {//code}();  時,  由於  function() {//code}  在" 先行編譯 " 階段已經被解釋過 , js 會跳過 function{//code} ,  試圖去執行  (); ,  故會報錯 ; 當 js 執行到  (function {// code})();  時,  由於  (function {// code})  是運算式, js 會去對它求解得到傳回值 ,  由於傳回值是一個函數 ,  故而遇到  ();  時,  便會被執行。另外, 函數轉換為運算式的方法並不一定要靠分組操作符 () ,我們還可以用 void 操作符, ~ 操作符, ! 操作符 ……6. function  foo() { foo(); }   //  這是一個自執行的函數,函數內部執行自身,遞迴 var foo =  function () { arguments.callee(); };   //  這是一個自執行的匿名函數,因為沒有標示名稱 , 必須使用 arguments.callee 屬性來執行自己 var foo =  function () { foo(); };   //  這可能也是一個自執行的匿名函數,僅僅是 foo 標示名稱引用它自身。如果你將 foo 改變成其它的,你將得到一個 used-to-self-execute 匿名函數( function () { /* code */ } ());   //  有些人叫這個是自執行的匿名函數(即便它不是),因為它沒有調用自身,它只是立即執行而已( function  foo() { /* code */ } ());   //  為函數運算式添加一個標示名稱,可以方便 Debug 。但一定命名了,這個函數就不再是匿名的了( function () { arguments.callee(); } ());( function  foo() { foo(); } ());   //  立即調用的函數運算式( IIFE )也可以自執行,不過可能不常用罷了 匿名函數與閉包閉包的英文單詞是closure ,這是 JavaScript 中非常重要的一部分知識,因為使用閉包可以大大減少我們的代碼量,使我們的代碼看上去更加清晰等等,總之功能十分強大閉包的含義:閉包說白了就是函數的嵌套,內層的函數可以使用外層函數的所有變數,即使外層函數已經執行完畢(這點涉及JavaScript 範圍鏈) function  checkClosure(){ var str = ’rain-man’;setTimeout( function(){ alert(str); } // 這是一個匿名函數, 2000);}checkClosure();這個例子看上去簡單,仔細分析下它的執行過程還是有許多知識點的:checkClosure 函數的執行是瞬間的(也許用時只是 0.00001 毫秒),在 checkClosure 的函數體內建立了一個變數 str ,在 checkClosure 執行完畢之後 str 並沒有被釋放,這是因為 setTimeout 內的匿名函數存在這對 str 的引用。待到 2 秒後函數體內的匿名函數被執行完畢 ,str 才被釋放用閉包來最佳化代碼: function  forTimeout(x, y){alert(x + y);}   function  delay(x , y  , time){setTimeout(’forTimeout(’ +  x + ’,’ +  y + ’)’ , time);}/**上面的delay 函數十分難以閱讀,也不容易編寫,但如果使用閉包就可以讓代碼更加清晰  function delay(x , y , time){setTimeout( function(){forTimeout(x , y)}, time);} */匿名函數最大的用途是建立閉包(這是JavaScript 語言的特性之一),並且還可以構建命名空間,以減少全域變數的使用 var oEvent = {};( function(){ var addEvent =  function(){ /* 代碼的實現省略了 */ }; function  removeEvent(){}oEvent.addEvent = addEvent;oEvent.removeEvent = removeEvent;})();在這段代碼中函數addEvent 和 removeEvent 都是局部變數,但我們可以通過全域變數 oEvent 使用它,這就大大減少了全域變數的使用,增強了網頁的安全性。 我們要想使用此段代碼oEvent.addEvent(document.getElementById(’box’) , ’click’ ,  function(){});var rainman = ( function(x , y){ return x + y;})(2 , 3);/* 也可以寫成下面的形式,因為第一個括弧只是協助我們閱讀,但是不推薦使用下面這種書寫格式var rainman =  function(x , y){ return x + y;}(2 , 3);*/在這裡我們建立了一個變數rainman ,並通過直接調用匿名函數初始化為 5 ,這種小技巧有時十分實用 var outer =  null;( function(){ var one = 1; function  inner (){one += 1;alert(one);}outer = inner;})();outer();    //2outer();    //3outer();    //4這段代碼中的變數one 是一個局部變數(因為它被定義在一個函數之內),因此外部是不可以訪問的。但是這裡我們建立了 inner 函數, inner 函數是可以訪問變數 one 的;又將全域變數 outer 引用了 inner ,所以三次調用 outer 會彈出遞增的結果 注意:1  閉包允許內層函數引用父函數中的變數,但是該變數是最終值/*< ul>< li>oneli>< li>twoli>< li>threeli>< li>oneli>  ul>  */var lists = document.getElementsByTagName(’li’);for(var i = 0 , len = lists.length ; i < len ; i++){lists[ i ].onmouseover = function(){alert(i);};}會發現當滑鼠移過每一個元素時總是彈出4 ,而不是我們期待的元素下標。這是為什麼呢?注意事項裡已經講了(最終值)。顯然這種解釋過於簡單,當 mouseover 事件調用監聽函數時,首先在匿名函數(  function(){ alert(i); } )內部尋找是否定義了  i ,結果是沒有定義;因此它會向上尋找,尋找結果是已經定義了,並且 i 的值是 4 (迴圈後的 i 值);所以,最終每次彈出的都是 4 解決方案一: var lists = document.getElementsByTagName(’li’);   for( var i = 0 , len = lists.length ; i < len ; i++){( function(index){lists[ index ].onmouseover =  function(){alert(index);};})(i);} 解決方案二: var lists = document.getElementsByTagName(’li’);   for( var i = 0, len = lists.length; i < len; i++){lists[ i ].$$index = i;    // 通過在 Dom 元素上綁定 $$index 屬性記錄下標lists[ i ].onmouseover =  function(){alert(this.$$index);};} 解決方案三: function  eventListener(list, index){list.onmouseover =  function(){alert(index);};}var lists = document.getElementsByTagName(’li’);   for(var i = 0 , len = lists.length ; i < len ; i++){eventListener(lists[ i ] , i);}2  記憶體泄露使用閉包十分容易造成瀏覽器的記憶體泄露,嚴重情況下會是瀏覽器掛死來源: 極客頭條

Javascript的匿名函數與自執行

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.