首頁  >  文章  >  web前端  >  javascript模組化程式設計詳解

javascript模組化程式設計詳解

PHPz
PHPz原創
2017-04-04 14:00:331447瀏覽

一、IIFE解釋

全拼Imdiately Invoked Function Expression,立即執行的函數#表達式

 像如下的程式碼所示,就是一個匿名立即執行函數:

(function(window, undefined){
  // 代码...    
})(window);

二、括號的意義

2.1 包住 function(){}的括號的意義

 這個括號的目的,是為了把function(){}#轉換成表達式。像一些函式庫的源碼,喜歡用如下方式代替:

~function(){
  // 代码...
}();

或這樣:

+function(){
  // 代码...
}();

 其實,作用都一樣,都是把function(){}轉換成一個可執行的表達式,方便執行。
 如果去掉該括號,則會報錯。因為單純的function(){}不是可執行的表達式,會直接報錯。如下圖:

javascript模組化程式設計詳解


# 2.1 第二個括號的意義

 理解了第一個括號的意義,第二個括號就很簡單了,就是執行表達式了。

三、參數的意義

 以這段程式碼為例子,講解參數

var wall = {};
(function(window, WALL, undefined){

})(window, wall);

 參數分為形參和實參。
function(window, WALL, undefined)三個參數為形參,第二個括號(window, wall)的兩個參數為實參。
 也即可以理解為 window == windowwall == WALL

2.1 普通形參考

 普通形參是指由windowwall這樣的實際變數傳入指定,可以為任何類型的變數。一個形參就對應一個實參

2.2 特殊形參就對應一個實參

2.2 特殊形參undefined
 為什麼形參要多寫一個undefined,這是一個很有趣的話題。

 可以知道這個範例,實參只有兩個,而形參有三個。所以在函數執行的時候,形參

undefined會預設賦值為undefined。

 形參考

undefined的作用如下:

2.2.1 防止特殊值undefined被惡意程式碼竄改。

 IE6等低版本瀏覽器,undefined是支援被修改的。而這個特殊值被修改後,像以下這種判斷就失效了。

if(wall == undefined){
  // 代码...
}
 所以,這裡多加一個形參的目的就是為了防止這種情況發生。只要在這個IIFE作用域內,undefined就能夠正常取得到。
 2.2.2 壓縮程式碼可以壓縮undefined

# 因為undefined作為形參,像YUI compressor這種類型的程式碼壓縮工具,可以將其相關的值進行壓縮,減小文件的體積。

四、寫法解析

4.1 普通寫法

var wall = {}; // 声明定义一个命名空间wall

// 定义方法
(function(window, WALL, undefined){
    // 给wall命名空间绑定方法say
    WALL.say = function(){
        console.log('hello');
    };
})(window, wall);

(function(window, WALL, undefined){
    // 给wall命名空间绑定方法 whoIam
    WALL.whoIam = function(){
        console.log('wall');
    };
})(window, wall);

// 调用
wall.say();
wall.whoIam();

 先定義一個命名空間,然後再為這個命名空間加東西。這是最普遍的寫法,也是最好理解的。  不足的地方就是必須先宣告一個命名空間,然後才能執行相關的綁定程式碼。存在順序載入的問題。

4.2 放大模式

var wall = (function(window, WALL, undefined){
    if(typeof WALL == 'undefined'){
        WALL = {};
    }

    // 给wall命名空间绑定方法say
    WALL.say = function(){
        console.log('hello');
    }

    return WALL; // 返回引用
})(window, wall);

var wall = (function(window, WALL, undefined){
    if(typeof WALL == 'undefined'){
        WALL = {};
    }

    // 给wall命名空间绑定方法 whoIam
    WALL.whoIam = function(){
        console.log('wall');
    }

    return WALL; // 返回引用
})(window, wall);

// 调用
wall.say();
wall.whoIam();
 放大模式的好處就是,可以不用考慮程式碼載入的先後順序。  因為js
允許

wall

變數進行重複var聲明,所以這段程式碼是可以執行的。  我可以把IIFE函數拆分成多個檔案來加載,而不會出現普通寫法需要注意的問題。

需要注意的點 1.IIFE的頭部,都要先進行檢查命名空間是否已經實例化,如果還沒實例化,則進行實例化。

 2.IIFE的尾部,都要return命名空間的引用,使後續程式碼能夠得到最新的

wall命名空間內容。

4.3 寬放大模式

(function(window, WALL, undefined){
    // 给wall命名空间绑定方法say
    WALL.say = function(){
        console.log('hello');
    }
})(window, window.wall || (window.wall = {}));

(function(window, WALL, undefined){
    // 给wall命名空间绑定方法 whoIam
    WALL.whoIam = function(){
        console.log('wall');
    }
})(window, window.wall || (window.wall = {}));

// 调用
wall.say();
wall.whoIam();
寬放大模式的重點注意的地方:
就是在實參部分的window.wall || (window.wall = {})
 用||運算子進行取巧。  如果window.wall是已經實例化的,非not defined。則直接傳回window.wall
的引用,賦值給形參WALL。不會執行||運算子後面的內容。
 如果window.wall尚未實例化,則進行實例化。這裡要注意的點是實例化是一個賦值運算,需要用括號包起來,變成表達式去執行,才不會報錯。  表達式(window.wall = {})執行完畢後,會傳回新物件###window.wall###的參考。 ###

宽放大模式的好处:是可以切割成多个文件进行加载,而不必考虑文件加载的先后顺序,不存在强耦合关系。
 当然,如果IIFE里面的方法互相引用,还是存在加载依赖的问题。这个问题可以用加载器Require.js等工具解决,这里就不讨论了。

五、分文件加载IIFE要注意的点

;(function(window, WALL, undefined){
    // 给wall命名空间绑定方法say
    WALL.say = function(){
        console.log('hello');
    }
})(window, window.wall || (window.wall = {}));

 眼尖的已经看出区别了,就是文件开始的地方,先写上分号;
 这样,多个文件合并的时候,才不会出现收尾相接,代码出现错乱的问题。比如下面这种情况:

// a.js 文件
wall.log()

// b.js 文件
(function(window, WALL, undefined){
    // 给wall命名空间绑定方法say
    WALL.say = function(){
        console.log('hello');
    }
})(window, window.wall || (window.wall = {}));

 由于a.js文件的wall.log()少写了分号,跟b.js文件合并后,js就会认为‘wall.log()(...)’是需要这么执行的,结果代码就报错了。


 觉得不错的,可以关注<a href="http://www.php.cn/js/js-weixinapp-module.html" target="_blank">模块化</a>这个系列的文章,容我后续码字,敬请期待!


以上是javascript模組化程式設計詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn