<strike id="cy2gs"><menu id="cy2gs"></menu></strike>
  • <del id="cy2gs"><dfn id="cy2gs"></dfn></del>
  • js 模塊化編程

    2018-9-14    seo達(dá)人

    如果您想訂閱本博客內(nèi)容,每天自動(dòng)發(fā)到您的郵箱中, 請點(diǎn)這里

    了解一個(gè)技術(shù),首先要了解這個(gè)技術(shù)產(chǎn)生的背景及解決的問題,而不應(yīng)該只是單純的知道該怎么用。之前的狀態(tài)可能就是只是為了了解而了解,并不知道實(shí)際產(chǎn)生的原因及帶來的好處,所以今天就來總結(jié)一下。

    1. 什么是模塊化編程

    來看百度百科的定義

    模塊化程序設(shè)計(jì)是指在進(jìn)行程序設(shè)計(jì)時(shí)將一個(gè)大程序按照功能劃分為若干小程序模塊,每個(gè)小程序模塊完成一個(gè)確定的功能,并在這些模塊之間建立必要的聯(lián)系,通過模塊的互相協(xié)作完成整個(gè)功能的程序設(shè)計(jì)方法。

    比如 java 的 import,C# 的 using。我的理解是通過模塊化編程,可以將不同的功能獨(dú)立出來,修改某個(gè)功能時(shí)不會(huì)對其他功能產(chǎn)生影響。

    2. 為什么要模塊化

    來看下面一個(gè)例子

    // A.js function sayWord(type){ if(type === 1){
            console.log("hello");
        }else if(type === 2){
            console.log("world");
        }
    } // B.js function Hello(){ sayWord(1);
    } // C.js Hello()  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    假設(shè)上面三個(gè)文件,B.js 引用了 A.js 里面的內(nèi)容,C.js 又引用了 B.js 里面的內(nèi)容,如果編寫 C.js 的人只知道引用了 B.js,那他就不會(huì)引用 A.js 就會(huì)導(dǎo)致程序出錯(cuò),而且文件的引用順序也不能出錯(cuò)。給整體代碼的調(diào)試修改帶來不便。

    還有個(gè)問題,上述代碼暴露了兩個(gè)全局變量,容易造成全局變量的污染

    3. AMD

    AMD 即 Asynchronous Module Definition(異步模塊定義)。采取異步加載的方式加載模塊,模塊的加載不會(huì)影響它后面的語句執(zhí)行。而且只有用到的時(shí)候才會(huì)去加載相關(guān)文件,屬于瀏覽器端的標(biāo)準(zhǔn)

    假設(shè)下面這種情況

    // util.js define(function(){ return {
            getFormatDate:function(date,type){ if(type === 1){ return '2018-08-9' } if(type === 2){ return '2018 年 8 月 9 日' }
            }
        }
    }) // a-util.js define(['./util.js'],function(util){ return {
            aGetFormatDate:function(date){ return util.getFormatDate(date,2)
            }
        }
    }) // a.js define(['./a-util.js'],function(aUtil){ return {
            printDate:function(date){ console.log(aUtil.aGetFormatDate(date))
            }
        }
    }) // main.js require(['./a.js'],function(a){ var date = new Date()
        a.printDate(date)
    })
    console.log(1); // 使用 // <script src = "/require.min.js" data-main="./main.js"></script>   
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    頁面上先打印 1,然后才會(huì)打印 2018 年 8 月 9 日。因此 AMD 的加載并不會(huì)影響后續(xù)的語句執(zhí)行。

    如果不是異步加載會(huì)出現(xiàn)什么情況呢

    var a = require('a');
    console.log(1) 
    
    • 1
    • 2

    后面的語句需要等待 a 加載完成才能執(zhí)行,如果加載時(shí)間過長,整個(gè)程序都會(huì)卡在這。因此,瀏覽器不能同步加載資源,這也是 AMD 的產(chǎn)生背景。

    AMD 是在瀏覽器端實(shí)現(xiàn)模塊化開發(fā)的規(guī)范。由于該規(guī)范不是 JavaScript 原始支持的,使用 AMD 規(guī)范進(jìn)行開發(fā)的時(shí)候需要引入第三方的庫函數(shù),也就是 RequireJS。

    RequireJS 主要解決的問題

    • 使 JS 異步加載,避免頁面失去響應(yīng)
    • 管理代碼之間的依賴性,有利于代碼的編寫和維護(hù)

    下面來看看如何使用 require.js

    要想使用 require.js,首先要 define

    // ? 代表該參數(shù)可選 define(id?, dependencies?, factory); 
    
    • 1
    • 2
    • id:指的是定義的模塊的名字
    • dependencies:是定義的模塊所依賴模塊的數(shù)組
    • factory:為模塊初始化要執(zhí)行的函數(shù)或?qū)ο蟆H绻麨楹瘮?shù),它應(yīng)該只被執(zhí)行一次。如果是對象,此對象應(yīng)該為模塊的輸出值。

      具體的規(guī)范說明可以參考 AMD (中文版) 
      舉個(gè)例子,創(chuàng)建一個(gè)名為 “alpha” 的模塊,使用了 require,exports,和名為 “beta” 的模塊:

    define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb();
           }
       }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    一個(gè)返回對象的匿名模塊:

    define(["alpha"], function (alpha) { return {
             verb: function(){ return alpha.verb() + 2;
             }
           };
       }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    一個(gè)沒有依賴性的模塊可以直接定義對象:

    define({
         add: function(x, y){ return x + y;
         }
       }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    如何使用

    AMD 采用 require 語句加載模塊

    require([module],callback); 
    
    • 1
    • module:是一個(gè)數(shù)組,里面的成員是要加載的模塊
    • callback:加載成功之后的回調(diào)函數(shù)

    例如

    require(['./a.js'],function(a){ var date = new Date()
        a.printDate(date)
    }) 
    
    • 1
    • 2
    • 3
    • 4

    具體的使用方法如下

    // util.js define(function(){ return {
            getFormatDate:function(date,type){ if(type === 1){ return '2018-08-09' } if(type === 2){ return '2018 年 8 月 9 日' }
            }
        }
    }) // a-util.js define(['./util.js'],function(util){ return {
            aGetFormatDate:function(date){ return util.getFormatDate(date,2)
            }
        }
    }) // a.js define(['./a-util.js'],function(aUtil){ return {
            printDate:function(date){ console.log(aUtil.aGetFormatDate(date))
            }
        }
    }) // main.js require(['./a.js'],function(a){ var date = new Date()
        a.printDate(date)
    }) // 使用 // <script src = "/require.min.js" data-main="./main.js"></script>  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    假設(shè)這里有 4 個(gè)文件,util.js,a-util.js 引用了 util.js,a.js 引用了 a-util.js,main.js 引用了 a.js。

    其中,data-main 屬性的作用是加載網(wǎng)頁程序的主模塊。

    上例演示了一個(gè)主模塊最簡單的寫法,默認(rèn)情況下,require.js 假設(shè)依賴和主模塊在同一個(gè)目錄。

    使用 require.config() 方法可以對模塊的加載行為進(jìn)行自定義。require.config() 就寫在主模塊(main.js)的頭部,參數(shù)是一個(gè)對象,這個(gè)對象的 paths 屬性指定各個(gè)模塊的加載路徑

    require.config({
        paths:{ "a":"src/a.js", "b":"src/b.js" }
    }) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    還有一種方法是改變基礎(chǔ)目錄(baseUrl)

    require.config({
    
        baseUrl: "src",
    
        paths: { "a": "a.js", "b": "b.js",
    
        }
    
      }); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4. CommonJS

    commonJS 是 nodejs 的模塊化規(guī)范,現(xiàn)在被大量用在前端,由于構(gòu)建工具的高度自動(dòng)化,使得使用 npm 的成本非常低。commonJS 不會(huì)異步加載 JS,而是同步一次性加載出來

    在 commonJS 中,有一個(gè)全局性的方法 require(),用于加載模塊,例如

    const util = require('util'); 
    
    • 1

    然后,就可以調(diào)用 util 提供的方法了

    const util = require('util'); var date = new date();
    util.getFormatDate(date,1); 
    
    • 1
    • 2
    • 3

    commonJS 對于模塊的定義分三種,模塊定義(exports),模塊引用(require)和模塊標(biāo)示(module)

    exports() 對象用于導(dǎo)出當(dāng)前模塊的變量或方法,唯一的導(dǎo)出口。require() 用來引入外部模塊。module 對象代表模塊本身。

    舉個(gè)栗子

    // util.js module.exports = {
        getFormatDate:function(date, type){ if(type === 1){ return '2017-06-15' } if(type === 2){ return '2017 年 6 月 15 日' }
        }
    } // a-util.js const util = require('util.js')
    module.exports = {
        aGetFormatDate:function(date){ return util.getFormatDate(date,2)
        }
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    或者下面這種方式

     // foobar.js // 定義行為 function foobar(){ this.foo = function(){ console.log('Hello foo');
            } this.bar = function(){ console.log('Hello bar');
              }
     } // 把 foobar 暴露給其它模塊 exports.foobar = foobar; // main.js //使用文件與模塊文件在同一目錄 var foobar = require('./foobar').foobar,
    test = new foobar();
    test.bar(); // 'Hello bar' 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5. ES6 Module

    ES6 模塊的設(shè)計(jì)思想是盡量靜態(tài)化,使得編譯時(shí)就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量,而 CommonJS 和 AMD 模塊都只能在運(yùn)行時(shí)確定這些關(guān)系。如 CommonJS 加載方式為 “運(yùn)行時(shí)加載”,ES6 的加載方式為 “編譯時(shí)加載” 或者靜態(tài)加載,即 ES6 可以在編譯時(shí)就完成模塊加載,效率比 CommonJS 模塊的加載方式高。

    ES6 模塊自動(dòng)采用嚴(yán)格模式,不管有沒有在模塊頭部加上 “use strict”。

    ES6 export 語句輸出的接口與其對應(yīng)的值是動(dòng)態(tài)綁定關(guān)系,即通過該接口可以取到模塊內(nèi)部實(shí)時(shí)的值。而 CommonJS 模塊輸出的是值的緩存,不存在動(dòng)態(tài)更新。

    ES6 與 CommonJS 模塊的差異

    • CommonJS 模塊輸出的是一個(gè)值的復(fù)制,ES6 模塊輸出的是值的引用。
    • CommonJS 模塊是運(yùn)行時(shí)加載,ES6 模塊是編譯時(shí)輸出接口。
    • CommonJS 中的 this 指向當(dāng)前模塊,ES6 模塊 this 為 undefined

    第二個(gè)差異是因?yàn)?CommonJS 加載的是一個(gè)對象(即 Module.exports 屬性),該對象只有在腳本運(yùn)行結(jié)束時(shí)才會(huì)生成,而 ES6 模塊不是對象,它的對外接口只是一種靜態(tài)定義,在代碼靜態(tài)解析階段就會(huì)生成。

    總結(jié)

    CommonJS 采用了服務(wù)器優(yōu)先的策略,使用同步方式加載模塊,而 AMD 采用異步加載的方式。所以如果需要使用異步加載 js 的話建議使用 AMD,而當(dāng)項(xiàng)目使用了 npm 的情況下建議使用 CommonJS。

    藍(lán)藍(lán)設(shè)計(jì)www.skdbbs.com )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 平面設(shè)計(jì)服務(wù)


    日歷

    鏈接

    個(gè)人資料

    存檔

    主站蜘蛛池模板: 国产精品自在线拍国产电影| 欧美精品在线免费| 精品亚洲欧美无人区乱码| 精品日韩亚洲AV无码| 久久精品国产福利国产琪琪| 欧美精品华人在线| 国产精品亚韩精品无码a在线| 亚洲精品NV久久久久久久久久| 国产精品人成在线观看| 国产精品麻豆高清在线观看| 青青草原精品99久久精品66| 国产三级精品久久| 亚洲精品国产成人专区| 国产99久久精品一区二区| 久久国产乱子伦免费精品| 尤物TV国产精品看片在线| 久久精品二区| 国产亚洲精品不卡在线| 成人国产精品秘 果冻传媒在线| 成人午夜精品网站在线观看| 老司机67194精品线观看| 亚洲国产精品一区二区第一页| 免费人欧美日韩在线精品| 精品人妻系列无码人妻免费视频 | 久久99精品久久久久久齐齐 | 成人精品一区二区三区中文字幕 | 国产精品无码无卡在线播放| 熟女精品视频一区二区三区| 中文字幕精品无码一区二区| 亚欧洲精品在线视频免费观看| 久久乐国产精品亚洲综合| 精品第一国产综合精品蜜芽| 精品久久久久国产免费| 精品久久久久久国产牛牛app| 精品人妻少妇一区二区三区| 久久国产乱子伦精品免费午夜| 精品成人一区二区三区四区| 精品无码三级在线观看视频| 精品精品国产高清a毛片| 精品久久久久久无码国产| 久久久精品人妻无码专区不卡|