學習js函數--自執行函數

来源:http://www.cnblogs.com/jiangshichao/archive/2017/07/11/7152855.html
-Advertisement-
Play Games

我在寫代碼時候經常會在tpl的<script>里寫類似的代碼: 剛開始的時候只知道寫了它不需要調用,直接執行,就這樣依葫蘆畫瓢,我寫了很多代碼。說道這,還要說說這貨的載入順序,如果把代碼直接寫到script標簽里,當頁面載入完這個script標簽就會執行裡邊的代碼了。如果在這代碼里用到了未載入的do ...


我在寫代碼時候經常會在tpl的<script>里寫類似的代碼:

$(function(){
    alert("我好餓");
});

剛開始的時候只知道寫了它不需要調用,直接執行,就這樣依葫蘆畫瓢,我寫了很多代碼。說道這,還要說說這貨的載入順序,如果把代碼直接寫到script標簽里,當頁面載入完這個script標簽就會執行裡邊的代碼了。如果在這代碼里用到了未載入的dom或者調用了未載入的方法,是會報錯的。言歸正傳,這個函數其實就是自執行函數,很多人會比較專業地稱為“立即調用的函數表達式”。

在這裡,我引用下limlimlim的博客,感覺比較專業...原址http://blog.csdn.net/limlimlim/article/details/9198111

當你聲明類似function foo(){}或var foo = function(){}函數的時候,通過在後面加個括弧就可以實現自執行,例如foo(),看代碼:

// 因為想下麵第一個聲明的function可以在後面加一個括弧()就可以自己執行了,比如foo(),
// 因為foo僅僅是function() { /* code */ }這個表達式的一個引用
 
var foo = function(){ /* code */ }
 
// ...是不是意味著後面加個括弧都可以自動執行?
 
function(){ /* code */ }(); // SyntaxError: Unexpected token (
//

上述代碼,如果甚至運行,第2個代碼會出錯,因為在解析器解析全局的function或者function內部function關鍵字的時候,預設是認為function聲明,而不是function表達式,如果你不顯示告訴編譯器,它預設會聲明成一個缺少名字的function,並且拋出一個語法錯誤信息,因為function聲明需要一個名字。

有趣的是,即便你為上面那個錯誤的代碼加上一個名字,他也會提示語法錯誤,只不過和上面的原因不一樣。在一個表達式後面加上括弧(),該表達式會立即執行,但是在一個語句後面加上括弧(),是完全不一樣的意思,他的只是分組操作符。

// 下麵這個function在語法上是沒問題的,但是依然只是一個語句
// 加上括弧()以後依然會報錯,因為分組操作符需要包含表達式
 
function foo(){ /* code */ }(); // SyntaxError: Unexpected token )
 
// 但是如果你在括弧()里傳入一個表達式,將不會有異常拋出
// 但是foo函數依然不會執行
function foo(){ /* code */ }( 1 );
 
// 因為它完全等價於下麵這個代碼,一個function聲明後面,又聲明瞭一個毫無關係的表達式: 
function foo(){ /* code */ }
 
( 1 );

要解決上述問題,非常簡單,我們只需要用大括弧將代碼的代碼全部括住就行了,因為JavaScript里括弧()裡面不能包含語句,所以在這一點上,解析器在解析function關鍵字的時候,會將相應的代碼解析成function表達式,而不是function聲明。

// 下麵2個括弧()都會立即執行

(function () { /* code */ } ()); // 推薦使用這個
(function () { /* code */ })(); // 但是這個也是可以用的

// 由於括弧()和JS的&&,異或,逗號等操作符是在函數表達式和函數聲明上消除歧義的
// 所以一旦解析器知道其中一個已經是表達式了,其它的也都預設為表達式了
// 不過,請註意下一章節的內容解釋

var i = function () { return 10; } ();
true && function () { /* code */ } ();
0, function () { /* code */ } ();

// 如果你不在意返回值,或者不怕難以閱讀
// 你甚至可以在function前面加一元操作符號

!function () { /* code */ } ();
~function () { /* code */ } ();
-function () { /* code */ } ();
+function () { /* code */ } ();

// 還有一個情況,使用new關鍵字,也可以用,但我不確定它的效率
// http://twitter.com/kuvos/status/18209252090847232

new function () { /* code */ }
new function () { /* code */ } () // 如果需要傳遞參數,只需要加上括弧()

上面所說的括弧是消除歧義的,其實壓根就沒必要,因為括弧本來內部本來期望的就是函數表達式,但是我們依然用它,主要是為了方便開發人員閱讀,當你讓這些已經自動執行的表達式賦值給一個變數的時候,我們看到開頭有括弧(,很快就能明白,而不需要將代碼拉到最後看看到底有沒有加括弧。

 

在這篇帖子里,我們一直叫自執行函數,確切的說是自執行匿名函數(Self-executing anonymous function),但英文原文作者一直倡議使用立即調用的函數表達式(Immediately-Invoked Function Expression)這一名稱,作者又舉了一堆例子來解釋,好吧,我們來看看:

// 這是一個自執行的函數,函數內部執行自身,遞歸
function foo() { foo(); }

// 這是一個自執行的匿名函數,因為沒有標示名稱
// 必須使用arguments.callee屬性來執行自己
var foo = function () { arguments.callee(); };

// 這可能也是一個自執行的匿名函數,僅僅是foo標示名稱引用它自身
// 如果你將foo改變成其它的,你將得到一個used-to-self-execute匿名函數
var foo = function () { foo(); };

// 有些人叫這個是自執行的匿名函數(即便它不是),因為它沒有調用自身,它只是立即執行而已。
(function () { /* code */ } ());

// 為函數表達式添加一個標示名稱,可以方便Debug
// 但一定命名了,這個函數就不再是匿名的了
(function foo() { /* code */ } ());

// 立即調用的函數表達式(IIFE)也可以自執行,不過可能不常用罷了
(function () { arguments.callee(); } ());
(function foo() { foo(); } ());

// 另外,下麵的代碼在黑莓5里執行會出錯,因為在一個命名的函數表達式里,他的名稱是undefined
// 呵呵,奇怪
(function foo() { foo(); } ());

希望這裡的一些例子,可以讓大家明白,什麼叫自執行,什麼叫立即調用。(我到這也才理解了一點,理論萬歲)

下麵 limlimlim還講了Module模式,這是我之後要學習的重要東西,當然在這之前還有閉包(頭大)

給各位看看例子吧

// 創建一個立即調用的匿名函數表達式
// return一個變數,其中這個變數里包含你要暴露的東西
// 返回的這個變數將賦值給counter,而不是外面聲明的function自身

var counter = (function () {
    var i = 0;

    return {
        get: function () {
            return i;
        },
        set: function (val) {
            i = val;
        },
        increment: function () {
            return ++i;
        }
    };
} ());

// counter是一個帶有多個屬性的對象,上面的代碼對於屬性的體現其實是方法

counter.get(); // 0
counter.set(3);
counter.increment(); // 4
counter.increment(); // 5

counter.i; // undefined 因為i不是返回對象的屬性
i; // 引用錯誤: i 沒有定義(因為i只存在於閉包)

 另外附上原版湯姆大叔的地址:http://www.cnblogs.com/TomXu/archive/2011/12/31/2289423.html

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [1]基本用法 [2]屬性參數 [3]JS觸發 [4]對比提示框 ...
  • 在JS給元素設置樣式屬性值,我們只能通過curEle.style[attr] = value 這種方式給元素設置行內樣式 下麵封裝一個給當前元素的某一個樣式屬性設置值的方法(增加在行內樣式上的):setCss() ...
  • 前面的話 提示框是一個比較常見的功能,一般來說是滑鼠移動到特定元素上時,顯示相關的提示語。本文將詳細介紹Bootstrap提示框 基本用法 Bootstrap框架中的提示框,結構非常簡單,常常使用的是按鈕<button>標簽或者鏈接<a>標簽來製作。不管是使用按鈕還是鏈接來製作提示框,他們都需要滿足 ...
  • 一、延遲腳本 defer HTML4.0中為<script> 標簽添加了個defer屬性。屬性的用途是表民腳本在執行時不會影響頁面的構造。 腳本會被延遲到頁面載入完畢的時候,執行。也就是當瀏覽器解析到</html> 標簽後才會執行代碼。在HTML5規範中,defer屬性中適用於外部腳本。 而家了de ...
  • 尋找BUG原因步驟 (1)首先通過v-on關鍵字尋找到 addHandler,此函數傳入的事件名竟然是 textinput(正確為textInput,I是大寫,而不是小寫),錯誤就定位在這了;然後往上層繼續尋找(即父函數) 註:(onRE.test(name)),var onRE = /^@|^v- ...
  • 當我們不會寫後端介面來測試ajax時,我們可以使用node環境來模擬一個後端介面。 1、模擬後端介面可參考http://www.cnblogs.com/heyujun-/p/6793900.html網站整站開發小例子,在打開命令視窗並轉到所在項目文件夾下在命令行中輸入npm install expr ...
  • 現在我們來看一下vue中的數據監聽事件$watch, js代碼: html代碼: 這就是數組的監聽,對於json我們也是一樣的,但是我們得給他一個深度監聽,$watch的第三個參數{deep:true}。 angular 中的數據交互有$http,同樣對於vue我們也是有數據交互的,有post,ge ...
  • 把info類下麵所有的a標簽鏈接後天加"#article"。 jQuery(document).ready(function($){ $('.info a').each(function(){ let Ahref = $(this).attr("href") + "#article"; $(this ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...