API模式:回調模式、配置對象、返回函數;node
初始化模式:即時函數、即時對象初始化、初始化分支;瀏覽器
性能模式:備忘模式、自定義模式緩存
1 //*********************** API模式 *********************** 2 /** 3 * ---------------------- 回調模式 ---------------------- 4 * 5 * 1>要寫出通用和可複用的代碼,回調模式能夠幫助實現這種通用化。 6 * 2>不須要預測和實現能想到的每一項功能,由於這樣會迅速使咱們的代碼膨脹, 7 * 而絕大多數用戶永遠不會須要其中大量的功能。相反,能夠專一於核心功能並提供「掛鉤」形式的回調函數, 8 * 這會使咱們很容易構建、擴展,以及自定義咱們的方法。 9 */ 10 //方式一 11 var findNodes = function () { 12 var i = 10000, 13 nodes = [], 14 found; 15 while (i) { 16 i -= 1; 17 //這裏是複雜的業務邏輯 18 nodes.push(found); 19 } 20 return nodes; 21 } 22 23 var hide = function (nodes) { 24 for (var i = 0, len = nodes.length; i < len; i += 1) { 25 nodes[i].style.display = 'none'; 26 } 27 } 28 29 hide(findNodes()); 30 31 //方式二 32 var findNodes = function (callback) { 33 var i = 10000, 34 nodes = [], 35 found; 36 while (i) { 37 i -= 1; 38 //這裏是複雜的業務邏輯 39 if (typeof callback === 'function') { 40 callback(found); 41 } 42 nodes.push(found); 43 } 44 return nodes; 45 } 46 47 var hide = function (node) { 48 node.style.display = 'none'; 49 } 50 51 findNodes(hide); 52 53 //簡潔點,將回調函數直接寫在findNodes函數中 54 findNodes(function (node) { 55 node.style.display = 'block'; 56 }) 57 58 /** 59 * ---------------------- 配置對象模式 ---------------------- 60 * 61 * 封裝傳遞參數爲一個對象,靈活了函數的調用方式,何樂而不爲 62 */ 63 function addPerson(name, gender, age, address) { 64 //... 65 } 66 67 //將參數封裝 68 var conf = { 69 name: 'king', 70 gender: 'male', 71 age: 25, 72 address: 'xxxxxx' 73 } 74 addPerson(conf); 75 76 //簡寫之 77 addPerson({ 78 name: 'king', 79 gender: 'male', 80 age: 25, 81 address: 'xxxxxx' 82 }) 83 84 /** 85 * ---------------------- 返回函數模式 ---------------------- 86 * 87 * 函數裏面返回函數,它建立了一個閉包,可使用這個閉包存儲一些私有數據, 88 * 而這些數據僅可被該返回函數訪問,但外部代碼卻沒法訪問。 89 */ 90 var setup = function () { 91 var count = 0; 92 return function () { 93 return count++; 94 } 95 } 96 var next = setup(); 97 next(); //1 98 next(); //2 99 next(); //3
//*********************** 初始化模式 *********************** /** * ---------------------- 即時函數模式 ---------------------- */ //文件module1.js中定義的模塊module1 (function () { //模塊1的全部代碼 })(); //文件module2.js中定義的模塊module2 (function () { //模塊2的全部代碼 })(); /** * ---------------------- 即時對象初始化模式 ---------------------- * * 這種模式的優勢與即時函數模式的優勢是相同的:能夠在執行一次性的初始化任務時保護全局命名空間。、 * 與僅僅將一堆代碼包裝到匿名函數的方法相比。這種模式看起來設計更多的語法特徵, * 可是若是初始化任何更加複雜(它們也每每的確比較複雜),它會使整個初始化過程顯得更有結構化。 * 其語法結構以下: * ({...}).init(); * ({...}.init()); */ ({ name: 'king', password: '123', say: function () { return 'I am ' + this.name + ', and my password is ' + this.password; }, init: function () { console.log(this.say()); } /** * 這種模式主要適用於一次性的任務,並且在init()完畢後也沒有保存對該對象的訪問。 * 若是想在init()完畢後保存對該對象的一個引用,能夠經過在init()尾部添加"return this;"語句實現該功能。 */ }).init(); //I am king, and my password is 123 /** * ---------------------- 初始化時分支模式 ---------------------- */ //每次調用utils.addListener()或utils.removeListener()時,都會重複地進行相同檢查 var utils = { addListener: function (elem, type, fn) { if (typeof window.addEventListener === 'function') { elem.addEventListener(type, fn, false); } else if (typeof window.attachEvent === 'function') { //IE elem.attachEvent('on' + type, fn); } else { elem['on' + type] = fn; } }, removeListener: function () { if (typeof window.removeEventListener === 'function') { elem.removeEventListener(type, fn, false); } else if (typeof window.detachEvent === 'function') { //IE elem.detachEvent('on' + type, fn); } else { elem['on' + type] = null; } } } //採用分支 var utils = { addListener: null, removeListener: null } //分開嗅探瀏覽器特徵,而後使用加載時分支僅執行一次嗅探 if (typeof window.addEventListener === 'function') { utils.addListener = function (elem, type, fn) { elem.addEventListener(type, fn, false); }; utils.removeListener = function (elem, type, fn) { elem.removeListener(type, fn, false); }; } else if (typeof window.detachEvent === 'function') { //IE utils.addListener = function (elem, type, fn) { elem.attachEvent('on' + type, fn); }; utils.removeListener = function (elem, type, fn) { elem.detachEvent('on' + type, fn); }; } else { utils.addListener = function (elem, type, fn) { elem['on' + type] = fn; }; utils.removeListener = function (elem, type, fn) { elem['on' + type] = null; }; }
//*********************** 性能模式 *********************** /** * ---------------------- 備忘模式 ---------------------- * * 使用函數屬性以便使得計算過的值無須再次計算 */ var myfunc = function (param) { if (!myfunc.cache[param]) { var result = {}; //...開銷很大的操做... myfunc.cache[param] = result; } return myfunc.cache[param]; } //緩存存儲 myfunc.cache = {}; /** * ---------------------- 自定義函數模式 ---------------------- * * 當函數有一些初始化準備工做要作,而且僅須要執行一次,那麼這個模式就很是有用。 * 由於並無任何理由去執行本能夠避免的重複工做,即該函數的一些部門可能並再也不須要。 * 在這種狀況下,自定義函數能夠更新自身的實現。使用此模式能夠顯著地幫助提高應用程序的性能, * 這是因爲從新定義的函數僅執行了更少的工做。 */ var scareMe = function () { alert('Boo!'); scareMe = function () { alert('Double boo!'); }; } scareMe(); //Boo! scareMe(); //Double boo! scareMe(); //Double boo!