/** * [function description] 函數功能描述 * @constrctor 用於表示構造函數 * @namespace namespaceName 用於命名包含全部對象的全局引用的名稱 * @method methodName 定義對象中的方法和方法名 * @property propertyName 定義對象中的屬性名 * @param {[type]} paramName [description] 參數 * @param {[type]} paramName [description] 參數 * @return {[type]} [description] 返回值 */
/** * 安全的數組檢測 * @param {unknown} value 待檢測數據 * @return {Boolean} 是否爲數組 */ function isArray(value) { if(typeof Array.isArray === 'undefined') { return Object.prototype.toString.call(value) === '[object Array]'; } else { return Array.isArray(value); } }
(function(){ // dosomething })(); var fnName=function(){ alert('Hello World'); }(); //函數表達式後面加括號,當javascript引擎解析到此處時能當即調用函數 function fnName(){ alert('Hello World'); }(); //不會報錯,可是javascript引擎只解析函數聲明,忽略後面的括號,函數聲明不會被調用 function(){ console.log('Hello World'); }(); //語法錯誤,雖然匿名函數屬於函數表達式,可是未進行賦值操做, //因此javascript引擎將開頭的function關鍵字當作函數聲明,報錯:要求須要一個函數名
即時函數能保證全局空間不會被臨時變量所污染。javascript
({ //配置常數 width:600, height:600, // 定義方法 gimmeMax: function() { return this.widht + "x" + this.height; }, // 初始化 init: function() { console.log(this.gimmeMax()); } }).init();
// 這樣只會在初始化EventUtil時執行條件語句,在綁定事件時不用每次都執行條件查詢 var EventUtil = { addEvent: null }; if(typeof window.addEventListener === 'function') { EventUtil.addEvent = function(el, type, handler) { el.addEventListener(type, handler, false); } }else if(typeof document.attachEvent === 'function') { EventUtil.addEvent = function(el, type, handler){ el.attachEvent('on' + type, handler); } }
配置對象java
當函數的參數過多時,爲了提供更整潔的API接口,能夠安全忽略可選參數,更加易於閱讀和維護,易於添加和刪除參數,便可以使用參數對象。設計模式
addPerson(obj){ // do something... } var conf = { name: "batman", firstName: "chris", lastName: "bale" }; addPerson(conf);
函數柯里化數組
當發現調用同一個函數,且傳遞的參數絕大多數是相同的時候,就能夠對該函數使用柯里化。緩存
function schonfinkelize(fn) { var slice = Array.prototype.slice, stored_args = slice.call(arguments, 1); return function() { var new_args = slice.call(arguments), args = stored_args.concat(new_args); return fn.apply(null, args); }; } function add(a, b, c, d, e) { return a + b + c + d + e; } // 使用示例:schonfinkelize(add, 1, 2, 3)(5, 5); // 輸出16
var MYOBJ = MYOBJ || {}; // 全局變量所有用大寫形式命名 // 避免重複命名的命名函數 MYOBJ.namespace = function (nameString) { var parts = nameString.split('.'), parent = MYOBJ, i; if(parts[0] === "MYOBJ") { parts = parts.slice(1); } for(i = 0; i< parts.length; i++) { if(typeof parent[parts[i]] === 'undefined') { parent[parts[i]]={}; } parent = parent[parts[i]]; } return parent; }
依賴關係
在函數或者模塊頂部顯式地聲明依賴的模塊。安全
var function myFunction() { //聲明依賴 var event = MYOBJ.event; // 使用依賴關係 // do something }
// 將私有方法揭示爲公有方法 var myarray; (function(){ // 私有屬性 var astr = '[object Array]' // 私有方法 function isArray(a) { return Object.prototype.toString.call(a) === astr; } // 公共接口 myarray = { isArray: isArray } })();
var MYOBJ = MYOBJ || {}; MYOBJ.namespace('MYOBJ.util.array'); MYOBJ.util.array = (function(){ // 私有屬性 var astr = '[object Array]'; // 私有方法 function isArray(a) { return Object.prototype.toString.call(a) === astr; } // 公共接口 return { isArray: isArray }; })();
function inherit(Child, Parent) { Child.prototype = new Parent(); }
構造函數繼承模式app
缺點是沒法從原型中繼承任何方法。優勢是能夠得到父對象自身成員的真實副本,並不會存在子對象意外覆蓋父對象的風險。函數
組合繼承模式學習
組合繼承模式缺點是父構造函數被調用了兩次,效率低下,且自身的屬性會經過構造函數和原型繼承兩次。優化
function inherit(Child, Parent) { Child.prototype = Parent.prototype; }
與默認方法相比,這樣作的優勢是效率比較高(不用執行和創建Parent的實例了),比較省內存。缺點是 Parent.prototype和Child.prototype如今指向了同一個對象,那麼任何對Child.prototype的修改,都會反映到Parent.prototype。
function inherit(Child, Parent) { var F = function () {}; // 臨時構造函數 F.prototype = Parent.prototype; Child.prototype = new F(); Child.uber = Parent.prototype; // 儲存超類 Child.prototype.constructor = Child; // 重置構造函數指針 }
2.原型繼承(無類繼承模式)
function object(parent){ function F() {}; F.prototype = parent; return new F(); } var parent = { name: "daddy" }; var child = object(parent);
這種繼承方式會共享相應的值,就像默認模式同樣,對子類型的修改都會反應到父類型上。
function createAnother(parent){ var child = object(parent); return child; }
適合對象不是自定義類型和構造函數的狀況。
寄生組合式繼承(引用類型最理想的繼承範式!)
在組合式繼承的基礎上優化,利用寄生繼承繼承父類的原型,使得繼承時只調用一次父類構造函數。
function inheritPrototype(child, parent){ // ES5有原生object.create方法代替object方法 var prototype = object(parent.prototype); prototype.constructor = child; child.prototype = prototype; } // 在組合繼承時將child.prototype = new Parent(); 改爲inheritPrototype(child, parent);
var singleton = function( fn ){ var result; return function(){ return result || ( result = fn .apply( this, arguments ) ); } } var createMask = singleton( function(){ return document.body.appendChild( document.createElement('div') ); });
var myNamespace = (function () { var myPrivateVar, myPrivateMethod; // A private counter variable myPrivateVar = 0; // A private function which logs any arguments myPrivateMethod = function( foo ) { console.log( foo ); }; return { // A public variable myPublicVar: "foo", // A public function utilizing privates myPublicFunction: function( bar ) { // Increment our private counter myPrivateVar++; // Call our private method using bar myPrivateMethod( bar ); } }; })();
模塊模式相對於真正的封裝概念更清晰,其次,模塊模式支持私有數據-所以,在模塊模式中,公共部分代碼能夠訪問私有數據,可是在模塊外部,不能訪問類的私有部分。 模塊模式的缺點是由於咱們採用不一樣的方式訪問公有和私有成員,所以當咱們想要改變這些成員的可見性的時候,咱們不得不在全部使用這些成員的地方修改代碼。