[JavaScript] 前端模塊編程實現

前端模塊化

前端模塊化

前端早期寫代碼都是全局變量滿天飛,這種狀況會形成全局命名空間污染,變量衝突等問題

var a = 1;
var b = 2;
function c(){}
function d(){}

後來採用了 js 的對象寫法,添加一個單獨的命名空間

var space = {
    a: 1,
    b: 2,
    c: function () {
        console.log('我是c');
        return this.a;
    },
    d: function () {
        console.log('我是d');
        return this.b;
    },
};

console.log(space.a);
console.log(space.b);
console.log(space.c());
console.log(space.d());

這樣就把變量掛載到 space 上了,而不是全局 window 上javascript

亦或是掛載到原型上(構造函數)

function Class() {
    this.a = 1;
    this.b = 2;
}

Class.prototype.c = function () {
    console.log('我是c');
    return this.a;
};
Class.prototype.d = function () {
    console.log('我是d');
    return this.b;
};

var instance = new Class();
console.log(instance.a); //1
console.log(instance.b); //2
console.log(instance.c()); //我是c //1
console.log(instance.d()); // 我是d //2

面向對象必定程度上解決了命名衝突的問題,可是 js 沒有私有變量,暴露內部變量,外部可有對內部數據進行修改外部能夠修改內部數據css

自執行函數(閉包)

(function (window) {
    let a = 1;
    let b = 2;

    function c() {
        console.log('我是c');
        return a;
    }

    function d() {
        console.log('我是d');
        return b;
    }

    window.module = {
        c:c,
        d:d,
    }
})(window);

//或者
var module = (function(){
    let a = 1;
    ...
    function c(){
        ...
    }
    ...
    return {
        a:a,
        c:c
    }
})()

這一方式能夠作到私有變量,模塊的基本寫法,好比 jqueryhtml

放大模式

(function () {
    var a = 1;
    window.module = {
        c: function () {
            return a
        },
    }
})();

(function (mod) {
    var b = 2;
    mod.d = function () {
        return b
    }
})(window.module)

console.log(module.c());
console.log(module.d());
console.log(module);

能夠實現模塊的分離和模塊的繼承,也具備私有變量,還能夠將自執行函數拆分紅多個文件進行加載,可是文件的執行順序有必定的要求,要先聲明對象 module前端

寬放大模式

//將上面給module添加功能的函數添加個默認值
(function (mod) {
    var b = 2;
    mod.d = function () {
        return b
    }
})(window.module || {})

能夠將模塊分紅不一樣的文件,同時文件不用再考慮加載順序不對致使 module 不存在的狀況java

  • 引入外部的庫
(function ($) {
    var a = 'red';
    $('.hello').css({ "background": a });
})(jQuery)
  • 自執行函數jquery

    自執行函數中()分組操做符是用來將 function(){}這個函數聲明轉化爲一種能夠執行的表達式,單純的 function(){}不是可執行的表達式,是一個函數聲明
    ()分組操做符能夠替換爲其餘操做符,好比 '#','+','-','!','void'......等等git

//這樣寫也是能夠的
+function ($) {
    var a = 'red';
    $('.hello').css({ "background": a });
}(jQuery)

function(){}是函數聲明,聲明的是一個匿名函數,而(function(){})()是一個表達式,而 js 在預編譯階段會解釋函數聲明,確會忽略表達式.因此到(function(){})的時候,該表達式會返回一個匿名函數,以後該匿名函數遇到後面的(),便會被執行github

var lis = document.querySelectorAll('li');
    for(var i=0;i<5;i++){
        lis[i].onclick = function(){
            alert(i); //5,5,5,5,5
        }
    }

    //又是這個經典的題目
    //這題最簡單仍是用元素屬性的方式去解決,好比

    for(var i=0;i<5;i++){
        lis[i].index = i;
        lis[i].onclick = function(){
            alert(this.index); //0,1,2,3,4
        }
    }

    //還有就是閉包
    for(var i=0;i<5;i++){
        (function(i){
            lis[i].onclick = function(){
                alert(i); //0,1,2,3,4
            }
        })(i)
    }
    //閉包就是在循環中執行,將i的值保存到當前做用域中,當click綁定的函數觸發時,會優先從離得最近的做用域去拿變量(就近原則)

    //因此,使用其餘的方式將當前i值保存到本身的做用域中就行
    for(var i=0;i<5;i++){
        click(i);
    }

    function click(i){
        lis[i].onclick = function(){
            alert(i); //0,1,2,3,4
        }
    }
    //這其實就跟上面的閉包有些相似了,閉包取i是從上級的匿名函數的做用域中取保存的i,而該方式就是從click函數的做用域中去取i值

模塊化的做用

  1. 解決全局變量污染的問題
  2. 一個文件一個模塊,可以更快速定位問題和解決問題,方便維護
  3. 解決文件的依賴關係問題
  4. 使大型項目的開發過程當中,每一個人負責每一個人的模塊編寫,方便大團隊開發工做

參考

相關文章
相關標籤/搜索