關於js的各大模式,還有不少東西沒有了解到,接觸的越多,愈加以爲這東西頗有用。javascript
<1>工廠模式php
簡單來講就是封裝後的代碼,簡單的工廠模式是很好理解的,關於它的做用,就是利用面向對象的方法,把一些對象封裝,使一些佔用空間多的,重複的代碼封裝起來。實現方法很是簡單,也就是在函數內建立一個對象,給對象賦予屬性以及方法再將對象返回便可。html
function creatper(name,age){ html5
var per=new Object(); //原料java
//加工node
per.name=name;mysql
per.age=age; sql
per.sayHi=function(){oracle
console.log(per.name+''+per.age); } 函數
return per; //出廠
}
var me=creatper('katherine',22);
me.sayHi();
console.log(me.name);
能夠看出,使用工廠模式,能夠重複調用這個per函數來生成不一樣屬性值得對象,這就像工廠同樣,批量生產,裏面的原料,加工,出廠都很清晰。可是你會發現工廠模式是沒法識別對象的類型,由於全都是object,不像Date,Array等,可是構造函數就不是了。這還只是簡單的工廠模式,複雜的工廠模式(抽象模式)等之後再回來詳細瞭解。
<2>構造函數模式
ECMAScript中構造函數能夠用來建立特定對象,相似於Array,Date等原生的js對象
function Student(name,age,classa){
this.name=name;
this.age=age;
this.classa=classa;
this.sayHello=function(){
console.log(this.name,this.age,this.classa);
}
}
var me=new Student("xiaoai",22,"大三");
console.log(me.classa);
me.sayHello();
console.log(me instanceof Student);//true
由代碼能夠看出,於工廠模式除了函數名不一樣之外,還要注意:構造函數名的首字母大寫(不過好像沒有嚴格規定)。構造函數也沒有顯示建立的對象,使用了this,直接把屬性和方法賦值給了this對象。沒有return語句,實例化的時候要使用new,並且它可以識別對象(這正是構造函數模式勝於工廠模式的地方)。
構造函數雖然好用,但也有很大的缺點,就是每次建立實例的時候都要從新建立一次方法,實際應用中,每次建立對象的時候屬性值不一樣,而對象的方法倒是相同的,因此建立兩次徹底相同的方法是沒有必要的,所以有人會說能夠把函數方法放到對象外面。以下:
function Student(name,age,classa){
this.name=name;
this.age=age;
this.classa=classa;
}
function sayHello(){
console.log(this.name,this.age,this.classa);
}
var me=new Student("xiaoai",22,"大三");
console.log(me.classa);
me.sayHello();
console.log(me instanceof Student);
這樣一改,就把sayhello函數設置成了全局函數,這樣一來Student的每個實例訪問的都是同一個函數,但是,在全局做用域中定義一個只供student使用的函數,就顯得有些過度了,若是在全局做用域中定義許多這樣僅供特定對象使用的方法,那就太浪費空間了,顯然也失去了面向對象所注重的封裝性了,所以徹底可使用原型解決這個問題。
<3>原型模式
js規定每個建立的函數都有prototype(原型)屬性,這個屬性是指針,指向一個對象,而這個對象的用途是包含由特定類型的全部實例所共享的屬性和方法,使用原型對象就可讓全部實例對象均包含這些屬性及方法。
function per(){}
per.prototype.name='xiaoai';
per.prototype.age=22;
per.prototype.course=['php','javascript','java','C#'];
per.prototype.say=function(){
console.log(this.name+this.age+this.course);
}
var per1=new per();
var per2=new per();
per1.name='katherine';
per1.course.push('Html5');
per1.say();
per2.say();
per2.course.pop();
關於原型模式的缺點,我想也是很明顯的,它省略了構造函數傳遞初始化參數這一環節,結果全部實例均在默認狀況下取得了相同的屬性值,雖然你能夠在後來作出更改,但一點都不方便,這樣還不是最大的問題,原型模式最大的問題是在於共享的本性所致使的,因爲共享,所以一個實例修改了引用,另外一個也隨之更改了屬性。所以通常不會單獨使用原型模式。
<4>混合模式(原型模式+構造函數)
function per(name,age,course){
this.name=name;
this.age=age;
this.course=course;
}
per.prototype.say=function(){
console.log(this.name+this.age+this.course);
}
var per1=new per('katherine',22,['C#','java','PHP','Javascript']);
var per2=new per ('xiaoai',21,['oracle','mysql','nodejs','html5']);
per1.say();
per2.say();
per1.course.pop();
per1.say();
per2.say();
由代碼能夠看出混合模式的分工:構造函數用於定義實例的屬性,而原型模式用於定義方法和一些共享的屬性。每一個實例都會有本身的屬性,但同時又共享着方法,最大限度的節省了內存。另外這種模式還支持傳遞初始參數。使用最普遍。
<5>動態模式
function per(name,age,course){
this.name=name;
this.age=age;
this.course=course;
if(typeof this.say!='function'){
per.prototype.say=function(){
console.log(this.name+this.age+this.course);
}
}
}
var per1=new per('katherine',22,['C#','java','PHP','Javascript']);
var per2=new per('xiaoai',22,['oracle','mysql','nodejs','html5']);
per1.say();
per2.say();
per1.course.pop();
per1.say();
per2.say();
動態原型模式將全部的信息都封裝進了構造函數中,經過構造函數中初始化原型,僅第一個對象實例實例化時初始化,經過判斷該方法是否有效存在而選擇是否須要初始化。大白話就是:若是去掉if的話,每new一次(即每當一個實例對象生產時),都會從新定義一個新的函數,而後掛到per.prototype.say上,而實際上,只須要定義一次就夠了,由於全部的實例都會共享此屬性的,因此若是去掉if的話,會形成沒有必要的時間和空間的浪費,而加上if後,只在new第一次實例化時會定義say方法,以後都不會再定義了。能夠看出對於這種模式建立的對象,是最好的了。
本文章參考了http://www.jb51.net/article/53823.htm,只供本人學習筆記使用。