第一個 W "What" -- 是什么?什么是插件,我就不照搬書本上的抽象概念了,我個人簡單理解就是,能方便實現某個功能的擴展工具.(下面我會通過簡單的例子來幫助讀者理解)
第二個 W "Why" -- 為什么? 為什么要有插件這種東西,首先結合第一個 W 來理解就是,使用插件的目的是方便我們實現某一個功能. 也就是說在編程過程中我們只需要找輪子,或者改輪子而不需要重新造輪子.節省開發時間,并且各司其職會更加專業(做得更好)。其次就是方便維護,因為每個功能模塊可以分得更清楚,所謂的松耦合。
第三個 W "How" -- 如何做?我們如何開發 JavaScript 插件?這是我們這片文章要談論的重點.
在討論如何做之前我們不妨先通過反向思維來看看插件的特點。我們從如何使用 Javascript 插件開始。
假設我們現在要使用插件 js-plugin.js
第一步:引入插件,注意依賴項,例如有些插件是基于 jquery 編寫的,先引入 jquery
第二步:通過插件提供的 API 實現我們所要的業務
以經典的 jquery 使用方法為例
由上述代碼可見,我們將某些功能,如 “sayHello” 給歸到 Helloword (模塊)中了。當然我們可以繼續在下面添加其他功能,但都歸于模塊 Helloword 來管理。這就是 Module 的體現。
使用方法(注意這里使用了 new )
var Hei = new Helloword('hello'); Hei.sayHello('Hello Word');var Hei2 = new Helloword('hi'); Hei2.sayHello('hi');
更直觀點,我們來看下完整的代碼
Module
運行結果如下
我們這里需要注意的是,每使用 new 創建出來的新對象都將開辟新的內存空間(新的一份copy),只要引用沒有釋放,那么該對象的占用的內存空間將不會被回收。那么如何避免過多浪費內存呢?一句話“釋放引用”,只需要釋放對該對象的所有引用,垃圾回收機制就會將該對象占用的內存空間回收。
var Hei = new Helloword('hello'); Hei.sayHello('Hello Word'); Hei = null;//解除引用
這樣還要“手動”內存管理,麻煩。如何讓該模塊在內存中只保留一份(copy)呢?請看下面一段代碼
var HelloWorld = (function(){ var _getDom = function(Id){ return document.getElementById(Id) } var _sayHello = function(Id,str){ _getDom(Id).innerHTML = str; } return { getDom:_getDom, sayHello:_sayHello } }())
使用方法
HelloWorld.sayHello('hello','hello text');
是的,正如你所見到的,不需要 new 了。使用時不再需要創建新對象,也就是說我們只保持了該對象在內存中的一份引用,也就是HelloWorld 對它的引用。當 HelloWorld 對其引用解除時其所占用的內存將得到釋放。上述代碼實質上是一個匿名閉包。如果對閉包不是很理解的朋友可以看看我寫的上一篇文章《淺析 JavaScript 中的閉包(Closures)》
四、插件基礎代碼
了解了上面的種種之后我們要開始直切主題了。
首先我們創建一個 js 文件 取名為 first-js-plugin.js(啥名字都行),鍵入以下代碼
; var plugin =(function(){ function _firstFunc(str){ console.log(str); }; return{ firstFunc: _firstFunc, }; })();
再創建一個 HTML頁面 取名為 pluginTest.html (啥名字都行)
完整代碼如下
可能有些童鞋會覺得有點陌生,那看下下面的代碼
var func = function(){ //code } func();
其實這兩段代碼是等價的,當然有點差別,第一個是匿名函數.作用都是定義一個函數并立即執行.
(function(){ //code })();
代碼分析:
最后面的小括號 () 表示執行該函數
(匿名函數) 小括號(分組表達式)包起來匿名函數的聲明,作用相當是將函數聲明轉為表達式,這樣才能執行,僅此而已
如果采取以下寫法
function(){ //code }();
編譯器報錯,問題是函數聲明無法執行,表達式才能執行
搞清楚這些之后我們回頭給下面的代碼加上分析,如下
;//JavaScript 弱語法的特點,如果前面剛好有個函數沒有以";"結尾,那么可能會有語法錯誤 /* plugin.api_funcs 給對象設置屬性,屬性值為 自調用匿名函數 這里涉及到js作用域鏈以及閉包的知識點 */ var plugin =(function(){ function _firstFunc(str){ alert(str); }; //返回API return{ firstFunc: _firstFunc }; })();
我們將代碼抽取一下(只為幫助理解,已經理解的朋友請忽略)
//01.定義變量 var plugin = 某對象; //02.創建對象并返回 (function(){//code;return ...})();//匿名執行函數 return 某對象 //然后看核心的返回 return{firstFunc: _firstFunc}; //說白了就是,通過某個key將一個函數存儲起來.使用時通過key訪問到這個函數 var plugin = {key:function(){//code}} //所以最終的體現如下 var plugin = {firstFunc: “具體的函數引用”}
所以我們最后才能通過,插件名.屬性 來使用插件,正如:
plugin.firstFunc("Hello ! I am firstFunc");
四、插件的幾種寫法
這里我就不墨跡了,直接上代碼,關鍵處會給注釋
面向對象思想 類方式
//自定義類 function plugin(){} //提供默認參數 plugin.prototype.str = "default param"; //提供方法(如果不傳參,則使用默認參數) plugin.prototype.firstFunc = function(str = this.str){ alert(str); } //創建"對象" var p = new plugin(); //調用方法 p.firstFunc("Hello ! I am firstFunc");//Hello ! I am firstFunc p.firstFunc();//default param
閉包方式
閉包方式就是我們剛剛一直在介紹
var plugin =(function(){ function _firstFunc(str){ alert(str); }; return{ firstFunc: _firstFunc, }; })();
第二種方式上的一些變化
(function(){ //定義一些默認參數 var _options={ default_word:"default hello" } //定義一些api var _plugin_api = { firstFunc:function(str = _options.default_word){ alert(str); return this;//返回當前方法 }, secondFunc:function(){ alert("secondFunc"); return this;//返回當前方法 } } //這里確定了插件的名稱 this.CJPlugin = _plugin_api; })(); CJPlugin.firstFunc("hello");//hello CJPlugin.firstFunc();//default hello CJPlugin.secondFunc();//secondFunc
結語
JavaScript 插件的相關知識今天暫時聊到這了.下篇文章筆者將通過實例來介紹如何開發一款屬于自己的省市區三級聯動插件.如果有朋友正在學習插件開發.那么下篇文章可能我們有更多可以探討的話題。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com