1、三種類型模式javascript
設計模式、編碼模式、反模式java
2、JavaScript基本概念設計模式
一、面向對象瀏覽器
五種基本類型:數字、字符串、布爾、undefine、null緩存
函數也是對象,也有屬性和方法安全
對象有兩種類型:一、原生的 ECMAScript 二、主機的,在主機環境中定義,如瀏覽器閉包
原生包括:內置對象和用戶自定義對象app
主機包括:window對象和全部DOM對象函數
二、原型工具
原型是個對象,每一個都會自動獲取一個Prototypes屬性,該屬性指向一個新的空對象
三、JSLint
javascript是一門解析語言沒有靜態編譯時檢查,JSLint是檢查JavaScript代碼質量的工具
本章討論一些高質量代碼的核心方法、模式和習慣,如避免全局變量、使用單個變量var的聲明、循環中緩存長度變量length和符合代碼的約定.
1、編寫可維護代碼
一、減小全局變量
全局對象能夠在函數外部使用this訪問
mylobal = "hello"; // 全局變量
console.log(mylobal);
console.log(window.mylobal);
console.log(window["mylobal"]);
全局變量的問題:一、第三方Javascript庫 二、廣告合做夥伴的腳本
釋放變量:使用var 建立的變量不能刪除,不使用var建立的隱含全局變量能夠刪除,隱含變量不是真正的變量,而是全局對象的屬性,能夠經過delete刪除
// 定義三個全局變量
var global_var = 1;
global_noar = 2;
(function(){
global_fromfunc = 3;
})
delete global_var; // false
delete global_noar; // true
delete global_fromfunc; // true
二、單一的var模式
用一個var在函數頂部進行變量的聲明
var a = 0,
b = 1;
三、for循環
當遍歷時存儲長度,
var oLi = document.getElementsByTagName("li");
for(var i=0, len=oLi.length; i< len; i++){ ... }
四、不在增長內置的原型
就是別在內置的構造函數內增長新功能,
五、switch模式
提升switch的可讀性和健壯性
var inspect = 0, result = "";
swith(inspect){
case 0:
result = "zero"; break;
case 1:
result = "one"; break;
default:
retult = "unknown";
}
若是不寫break語句會接着向下執行
6 、parseInt()的數值約定
parseInt()從一個字符串中獲取數值,第二個參數爲進制,但若是字符串爲0開頭就必須寫進制,如"08",parseInt("08", 10);不然在ie下會輸出
另外一種寫法能夠:
+"08"; 或者 Number("08")
1、對象字面量
// 定義一個空對象
var dog = {};
// 向對象加一個屬性和方法
dog.name = "benji";
dog.getName = function(){
return dog.name;
}
2、構造函靈敏
1 var Person = function(name){ 2 this.name = name; 3 this.say = function(){ 4 return this.name; 5 } 6 }
構造函數原型prototyp的做用
將say方法添加到this中,若是在任什麼時候間調用new Person()時都會在內存中建立一個新的函數,會使效率低下,由於建立多個person實例時也會建立多個say方法,解決方法是將他們添加到原型中prototype
函數的兩個特色:一、函數是一類對象 二、函數能夠提供一個做用域
一、全局做用域:function foo(){}
二、局部做用域:
function local(){
// 局部做用域
function bar(){};
return bar;
}
三、函數表達式 var bar = function(){ ... }
四、匿名函數 function(){ ... }; 沒有名稱,在自動函數或賦給一個變量時使用
五、即時執行函數 (function(){ ... })();
即時函數的參數:
(function(who, when){
console.log("i met" + who);
})("joe black", new Date())
即時函數的返回值:
var result = (function(){
return 2 + 3;
})();
1、命名空間模式
命名空間有助於減小全局變量的數量,而且避免合名衝突或過長的名字前綴
1 <script> 2 // 不安全代碼,好比兩個js文件中都有這會MYAPP的建立,這樣第二個會覆蓋掉第一個對象 3 var MYAPP = {}; 4 5 // 更好的代碼風格 6 if(typeof MYAPP === "undefined"){ 7 var MYAPP = {}; 8 } 9 10 // 或者使用 11 var MYAPP = MYAPP || {}; 12 </script>
檢測代碼須要太多的重複工做,若是想定義MYAPP.modeles.module就必須三次檢查,每次都須要檢查一次對象或屬性,可使用namespace()函數
1 <script> 2 MYAPP.namespace("MYAPP.modules.getName"); 3 4 // 至關於 5 MYAPP.modules.getName = {} 6 7 8 // 定義一個命名空間函數 9 var MYAPP = MYAPP || {}; 10 MYAPP.namespace = function(sName, newObj){ 11 var parts = sName.split("."), 12 argLen = arguments.length, 13 parent = MYAPP; 14 15 // 剝離最前面的全局變量 16 if(parts[0] == "MYAPP"){ 17 parts = parts.slice(1); 18 } 19 20 if(argLen == 2 && (typeof newObj === "object" || typeof newObj === "function")){ 21 for(var i= 0,len = parts.length; i<len; i++){ 22 if(i == len-1){ 23 parent[parts[i]] = $.extend(newObj, parent[parts[i]]); // 須要繼承以前的對象 24 } 25 else{ 26 // 若是不存在就建立一個新的屬性 27 if(typeof parent[parts[i]] === "undefined"){ 28 parent[parts[i]] = {}; 29 } 30 } 31 parent = parent[parts[i]]; 32 } 33 } 34 else{ 35 for(var i= 0,len = parts.length; i<len; i++){ 36 // 若是不存在就建立一個新的屬性 37 if(typeof parent[parts[i]] === "undefined"){ 38 parent[parts[i]] = {}; 39 } 40 parent = parent[parts[i]]; 41 } 42 } 43 44 return parent; 45 } 46 47 // 一、建立一個命名空間,並初始化命名空間的對象 48 var ssq = MYAPP.namespace("MYAPP.storage.getStorage", { 49 50 init: function(){ 51 this.bindEvent(); 52 }, 53 54 bindEvent: function(){ 55 console.log("bind All"); 56 } 57 58 }); 59 60 // 調用 61 ssq.init(); // 結果 bind All 62 63 // 二、建立一個命名空間,初始化時爲函數,其實使用對象也徹底能夠作到,MYAPP.namespace("MYAPP.storage", {showFun: function(){ console.log("匿名函數"); }}; 64 var dlt = MYAPP.namespace("MYAPP.storage.showFun", function(){ 65 console.log("匿名函數"); 66 }); 67 68 // 調用 69 dlt(); 70 </script>
2、私有屬性、方法
js中沒有私有成員的語法,能夠經過閉包,或內部變量來實現這種功能。
1 <script> 2 function Gadget(){ 3 4 // 私有成員 5 var name = "iPad"; 6 7 // 公有函數 8 this.getName = function(){ 9 return name; 10 } 11 } 12 13 var toy = new Gadget(); 14 console.log(toy.name); // undefined 15 console.log(toy.getName()); // iPad 16 </script>
3、特權方法
就是經過公有方法來訪問私有屬性,這個方法能夠叫作特權方法,上面的例子getName()就是個特權方法.
4、模塊模式
1 <script> 2 var myObj = (function(){ 3 4 // 私有成員 5 var name = "my, oh my"; 6 7 // 實現公有部分 8 return { 9 getName: function(){ 10 return name; 11 } 12 } 13 })(); 14 </script>
一、構造函數的模塊
1 <script> 2 var MYAPP = MYAPP || {}; 3 4 // 命名空間函數 5 MYAPP.namespace = function(sName, newObj){ 6 var parts = sName.split("."), 7 argLen = arguments.length, 8 parent = MYAPP; 9 10 // 剝離最前面的全局變量 11 if(parts[0] == "MYAPP"){ 12 parts = parts.slice(1); 13 } 14 15 if(argLen == 2 && (typeof newObj === "object" || typeof newObj === "function")){ 16 for(var i= 0,len = parts.length; i<len; i++){ 17 if(i == len-1){ 18 parent[parts[i]] = $.extend(newObj, parent[parts[i]]); // 須要繼承以前的對象 19 } 20 else{ 21 // 若是不存在就建立一個新的屬性 22 if(typeof parent[parts[i]] === "undefined"){ 23 parent[parts[i]] = {}; 24 } 25 } 26 parent = parent[parts[i]]; 27 } 28 } 29 else{ 30 for(var i= 0,len = parts.length; i<len; i++){ 31 // 若是不存在就建立一個新的屬性 32 if(typeof parent[parts[i]] === "undefined"){ 33 parent[parts[i]] = {}; 34 } 35 parent = parent[parts[i]]; 36 } 37 } 38 39 return parent; 40 } 41 42 MYAPP.namespace("MYAPP.util"); // 建立一個命名空間 43 MYAPP.util = (function(){ 44 45 // 依賴 46 var oLib = MYAPP.lib; 47 48 // 建立構造函數 49 function Constr(){ 50 this.elements = "siguang"; 51 } 52 53 Constr.prototype.version = "2.0"; 54 Constr.prototype.showMessage = function(){ 55 console.log(this.version, this.elements); 56 } 57 58 var oConstr = new Constr(); 59 60 return oConstr; 61 }()); 62 63 console.log(MYAPP); 64 65 // 調用 66 MYAPP.util.showMessage(); // 67 </script>
二、將全局變量導入到模塊中
1 <script> 2 MYAPP.utilities.module = (function(app, global){ 3 // 引用全局對象 4 // 能夠轉成局部變量 5 // 全局應用程序命名空間對象 6 })(MYAPP, this) 7 </script>
1、包裝對象
什麼是包裝對象
var str = "ssssssss";
str.charAt(3);
str.substring(2);
通常方法是調用的是對象,而str是字符串,這就是用到了包裝對象,基本類型都有本身的包裝對象
例如:字符串包裝類型是String 數字是Number 布爾是Boolean,爲何str能夠調用字符串的方法,看下面的例子
1 <script> 2 var str = new String("haha"); // 將字符串到String對象 3 4 // String的對象的方法 5 String.prototype.charAt = function(n){ 6 // .... 7 } 8 </script>
var str = "haha"; // 這句正常定義變量
str.charAt(2); // 這裏基本類型str會找到對應包裝對象的方法,將屬性及方法賦給基本類型,而後包裝對象消失
1、類式繼承
類式繼承的幾種寫法:
一、默認模式
1 <script> 2 3 // 父構造函數 4 function Parent(name){ 5 this.name = name || "siguang"; 6 this.age = "30"; 7 this.setGame = function(){ 8 console.log(this.age); 9 } 10 } 11 12 // 向該原型添加功能 13 Parent.prototype.say = function(){ 14 return this.name; 15 } 16 17 // 空構造函數 18 function Child(name, age){ 19 this.age = age; 20 Parent.call(this, name); // 改變父類的屬性,不然調用的就是父類的屬性 21 } 22 23 // 繼承方法,封裝了一個 24 inherit(Child, Parent); 25 26 function inherit(C, P){ 27 C.prototype = new P(); // 繼承方法 28 } 29 30 var oC = new Child("lulu", 28); 31 console.log(oC.say()); // lulu 32 oC.setGame(); // 30 33 </script>
類式繼承繼承父類的屬性和方法,若是改變其屬性須要將改變指針Parent.call(this, name);
此模式的缺點:同時繼承兩個對象的屬性,將子類傳入age時this.age = age 輸出的並非預期的28而仍是父類的30,這也就是第二種模式
二、共享原型
修改了inherit方法
function inherit(C, P){
C.prototype = P.prototype; // 缺點:在繼承鏈的某一個子對象或孫對象修改了原型,會影響到父對象和祖先對象.
}
三、臨時構造函數