1. 程式人生 > >JavaScript中立即執行函式例項詳解 轉載 作者:李牧羊

JavaScript中立即執行函式例項詳解 轉載 作者:李牧羊

javascript和其他程式語言相比比較隨意,所以javascript程式碼中充滿各種奇葩的寫法,有時霧裡看花,當然,能理解各型各色的寫法也是對javascript語言特性更進一步的深入理解。這篇文章主要給大家介紹了關於JavaScript中立即執行函式的相關資料,需要的朋友可以參考下。

前言

js立即執行函式可以讓你的函式在建立後立即執行,js立即執行函式模式是一種語法,可以讓你的函式在定義後立即被執行,這種模式本質上就是函式表示式(命名的或者匿名的),在建立後立即執行。

( function(){…} )()和( function (){…} () )是兩種javascript立即執行函式的常見寫法,最初我以為是一個括號包裹匿名函式,再在後面加個括號呼叫函式,最後達到函式定義後立即執行的目的,後來發現加括號的原因並非如此。

下面話不多說了,來一起看看詳細的介紹吧。

通常我們宣告一個函式有以下幾種方式:

// 宣告函式f1
function f1() {
 console.log("f1");
}
// 通過()來呼叫此函式
f1();


//一個匿名函式的函式表示式,被賦值給變數f2:
var f2 = function() {
 console.log("f2");
}
//通過()來呼叫此函式
f2();


//一個命名為f3的函式的函式表示式(這裡的函式名可以隨意命名,可以不必和變數f3重名),被賦值給變數f3:
var f3 = function f3() {
 console.log("f3");
}
//通過()來呼叫此函式
f3();

如果你看過一些自定義控制元件的話你會發現他們大多數都是沿用這種寫法:

(function() {
 ```
 // 這裡開始寫功能需求
 })(); 

這是我們常說的立即執行函式(IIFE),顧名思義,也就是說這個函式是立即執行函式體的,不需要你額外去主動的去呼叫,一般情況下我們只對匿名函式使用IIFE,這麼做有兩個目的:

     一是不必為函式命名,避免了汙染全域性變數 

     二是IIFE內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變數。

如果看到這兩句話無法理解,那麼先從IIFE的執行原理說起。 

因為IIFE通常用於匿名函式,這裡就用簡單的匿名函式作為栗子:

var f = function(){
 console.log("f");
}
f();

我們發現這裡f只是這個匿名函式的一個引用變數,那麼既然f()能夠呼叫這個函式,我把f替換成函式本身可以麼:

function(){
 console.log("f"); 
}();

執行之後得到如下結果:

Uncaught SyntaxError: Unexpected token (

產生這個錯誤的原因是,Javascript引擎看到function關鍵字之後,認為後面跟的是函式宣告語句,不應該以圓括號結尾。解決方法就是讓引擎知道,圓括號前面的部分不是函式定義語句,而是一個表示式,可以對此進行運算,這裡區分一下函式宣告和函式表示式:

1、函式宣告(即我們通常使用function x(){}來宣告一個函式)

function myFunction () { /* logic here */ }

2、函式表示式(類似以這種的形式)

var myFunction = function () { /* logic here */ };
var myObj = {
 myFunction: function () { /* logic here */ }
};

小學我們就學過用()括起來的表示式會先執行,就像下面這樣:

1+(2+3) //這裡先執行小括號裡面的內容沒有意見撒

其實在javascript中小括號也有相似的作用,Javascript引擎看到function關鍵字會認為是函式宣告語句,那麼如果Javascript引擎優先看到小括號會怎麼樣:

//用小括號把函式包裹起來
(function(){
  console.log("f");  
})();

函式成功執行了:

f //控制檯輸出

這種情況下Javascript引擎就會認為這是一個表示式,而不是函式宣告,當然要讓Javascript引擎認為這是一個表示式的方法還有很多:

!function(){}();
+function(){}();
-function(){}();
~function(){}();
new function(){ /* code */ }
new function(){ /* code */ }() // 只有傳遞引數時,才需要最後那個圓括號。
……

回到前面的問題,為什麼說IIFE這種形式避免了汙染全域性變數,如果你見過別人寫的jquery外掛,裡面通常會有類似這樣的程式碼:

(function($){
  ```
  //外掛實現程式碼
})(jQuery);

這裡的jquery其實是該匿名函式的引數,聯想一下我們呼叫匿名函式時候是用f()那麼匿名帶引數的就是f(args)對吧,這裡把jquery作為引數傳入該函式,那麼在函式內部使用形參$的時候就不會影響到外部環境,因為有些外掛也會用到$這個限定符,你在這個函式內部可以隨意折騰。