[修練之路-JS]2. JS and jQuery's Module Design Pattern
參考文件:Essential JavaScript And jQuery Design Patterns – A Free New Book, JavaScript Module Pattern: In-Depth
JavaScript 模組我們可以用類物件導向的方式來說明,
"封裝" :
在前一章中已經用過的"匿名closures"語法:
(function(){ //anonymous
var c = 10; // 私變數
}());
document.write(c); // 無法使用 c 變數
因為JavaScript在處理變數, 若沒有宣告var則為全域變數
(function(){ //anonymous function
c = 13; // 全域變數
})();
document.write(c); // 可以使用 c 變數
全域變數可能為造成封裝內容的程式發生問題, 故可以將他修改,
如: 全域變數jQuery 較 全域變數$ 效能佳, 故在下方的範例中直接將變更$修改為對照到全域變數jQuery, 而非全域變數$
(function($){ // $ = jQuery
$('a[id="link"]'); // = jQuery('a[id="link"]');
})(jQuery);
預防沒有參數
var m = (function(m){
m.p = 1; // 新增一個屬性
m.f = function(){ return ++ m.p ; } ; // 新增一個方法, 註:要用c.p來存取屬性
return m;
}(m ||{})); // 預防沒有參數
document.write(m.p + "<br />"); // 印出 1
document.write(m.f() + "<br />"); // 印出 2
簡單的模組化(物件) 範例
var m = (function(){
var c = {}; // 宣告一個物件
c.p = 1; // 新增一個屬性
c.f = function(){ return ++ c.p ; } ; // 新增一個方法, 註:要用c.p來存取屬性
return c;
}());
document.write(m.p + "<br />"); // 印出 1
document.write(m.f() + "<br />"); // 印出 2
// 另一種寫法
var m2 = (function(){
var p = 1; // 宣告私有屬性
var f = function(){ return ++ p ; } ; // 新增一個私有方法
return {
p: p,
f: f
};
}());
document.write(m2.p + "<br />"); // 印出 1
document.write(m2.f() + "<br />"); // 印出 2
做一個類似partial class
(function(){
var m = (function(){ // partial class - main
var c = {}; // 宣告一個物件
c.p = 1; // 新增一個屬性
c.f = function(){ return ++ c.p ; } ; // 新增一個方法, 註:要用c.p來存取屬性
return c;
}());
extendtions(m); // 呼叫另一個partial class
document.write(m.p + "<br />"); // 印出 1
document.write(m.f() + "<br />"); // 印出 2
document.write(m.p2 + "<br />"); // 印出 2 , defined in partial class
document.write(m.f2() + "<br />"); // 印出 3 , defined in partial class
}());
function extendtions(arg_m){
(function(m){ // partial class - second
m.p2 = 2; // 新增一個屬性
m.f2 = function() { return ++ m.p2; }; // 新增一個方法
return m;
}(arg_m));
}
"繼承"
var parent = (function(){
var p = {};
p.p = 1; // 新增一個屬性
p.f = function(){ return ++ p.p ; } ; // 新增一個方法
return p;
}());
var child = (function(p){
var c = {}, key;
for( key in p ){
if(p.hasOwnProperty(key)){
c[key] = p[key];
}
}
c.f = function(){ return -- c.p };
return c;
}(parent));
document.write(parent.p + "<br />"); // 印出 1
document.write(parent.f() + "<br />"); // 印出 2
document.write(child.p + "<br />"); // 印出 1
document.write(child.f() + "<br />"); // 印出 0
JavaScript 語法實在太活了, 還有很多進階的Module設計法, 因為比較少用, 就不繼續深究了.
以上的語法是用參數的方式來宣告, 若要用方式的方式宣告差別只在於
var obj = function(){
var p = {};
p.p = 1; // 新增一個屬性
p.f = function(){ return ++ p.p ; } ; // 新增一個方法
return p;
}; // 少一個括弧
document.write(new obj().p + "<br />"); // 可以用new
再加碼一個jQuery plugin sample
(function($){
$.fn.SayHello = function(name){
return this.each(function(){
$(this).text('Hello ' + name); // 將每一個元素內部文字都改成Hello XXX
});
};
}(jQuery));
$(function(){
$('a').SayHello('Hector'); // print 'Hello Hector'
});