這篇文章的目的是經過演示一個簡單的例子來介紹在JS中實例化和定義一個庫的正確方法,以優化他人編寫或維護本身的JS庫。javascript
在咱們深刻以前,我作了兩點假設:java
首先,我遇到了第一個麻煩,即如何正確的看待一個JavaScript庫。在C/C++中,一個庫是功能的集合,而且一般不須要很完美的結構。
而JavaScript的工做方式有所不一樣,所以我作了一些研究。最後的結論是,一個JavaScript庫是一個包含在對象中的獨立的模塊,不會在本身的做用域之外定義函數來污染全局命名空間。閉包
基於此,咱們能夠簡單的定義一個庫:架構
var Library = { name: "Candy", greet: function() { alert("Hello from the " + Library.name + " library."); } }
這個庫就是咱們字面意思上所說的對象。調用greet
函數,咱們要用:函數
Library.greet();
由於greet
是Library
對象的成員。如今,若是咱們指望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
方法依然是公有的,由於經過關鍵字this
將greet
定義爲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. 喜歡就關注我吧。