優雅的建立一個JavaScript庫

這篇文章的目的是經過演示一個簡單的例子來介紹在JS中實例化和定義一個庫的正確方法,以優化他人編寫或維護本身的JS庫。javascript

在咱們深刻以前,我作了兩點假設:java

  • 你知道簡單的JavaScript或C語言。
  • 你不打算使用jQuery。一般狀況下,一個JavaScript庫不須要任何依賴。

首先,我遇到了第一個麻煩,即如何正確的看待一個JavaScript庫。在C/C++中,一個庫是功能的集合,而且一般不須要很完美的結構。
而JavaScript的工做方式有所不一樣,所以我作了一些研究。最後的結論是,一個JavaScript庫是一個包含在對象中的獨立的模塊,不會在本身的做用域之外定義函數來污染全局命名空間。閉包

基於此,咱們能夠簡單的定義一個庫:架構

var Library = {
    name: "Candy",
    greet: function() {
        alert("Hello from the " + Library.name + "  library.");
    }
}

這個庫就是咱們字面意思上所說的對象。調用greet函數,咱們要用:函數

Library.greet();

由於greetLibrary對象的成員。如今,若是咱們指望name變量爲Library私有,應該怎麼作呢?遺憾的是,這種庫的定義方式沒法實現這一點。優化

並且,不只僅是在其餘文件中要經過Library.name來引用name變量,在Library中也要經過引用本身來引用name變量。這種解決方式看起來就不好勁。網站

解決這個問題的方法是將Library定義爲一個函數,在函數中定義對象。這種方式容許咱們建立並使用私有的變量和方法。以下:this

function Library() {
    var name = "Candy";
    this.greet = function() {
        alert("Hello from the " + name + " library.");
    }
}

在這種方式下,Library.name將不會暴露在全局,而且在Library內部也能被簡單的引用。greet方法依然是公有的,由於經過關鍵字thisgreet定義爲Library的一個成員。翻譯

肯定將什麼暴露給誰,是架構的簡單實踐。code

可是,如今咱們有了新的問題。在以下場景中,用戶已經定義了一個Library對象,而且引用了你的庫。

//用戶本身的Library對象
var Library = {
    book_num: 1123,
    category: [
        "science",
        "social"
    ]
}

//調用Library庫中的方法
Library.greet();

這時,你的Library定義被覆蓋,用戶還將被告知「引用錯誤」。

咱們有一個更好的解決方案:將你的library包裝在一個函數中,這個函數將在不存在命名衝突時被調用。以下:

(function(window) {
    'use strict';
    function define_library() {
        var Library = {};
        var name = "Candy";
        Library.greet = function() {
            alert("Hello from the " + name + " library.");
        }
        return Library;
    }
    
    if (typeof(Library) === "undefined") {
        window.library = define_library();
    } else {
        console.log("Library is already defined.");
    }
})(window);

首先,咱們解釋一下包裝整個library的閉包:

(function(window) {
    //CODE
})(window);

它的工做原理是,它包裝了在它其中定義的代碼,所以它擁有本身的命名空間。它也將會自動執行,由於末尾添加的(window)

接着,咱們介紹一下使用的use strict。這是一個可選配置,能夠在這裏瞭解更多相關知識。因爲咱們整個定義是一個閉包,因此只需聲明一次use strict,便可將嚴格模式應用於整個library

而後,咱們在define_library()函數中定義了Library對象,而且在函數最後返回了該對象。

最後,咱們經過typeof判斷當前是否有命名衝突,若是沒有,咱們將初始化咱們的Library對象。


要開始堅持寫文章啦。這是最近看到的一篇國外文章,以爲對本身有點幫助,就翻譯過來了,但願對你們也有所幫助,原文戳這裏

接下來的一篇文章,將封裝一個JS庫,實現購物網站上常見的圖片跟隨鼠標放大的功能。

to be continued. 喜歡就關注我吧。

相關文章
相關標籤/搜索