1. 程式人生 > >關於js的設計模式(簡單工廠模式,構造函數模式,原型模式,混合模式,動態模式)

關於js的設計模式(簡單工廠模式,構造函數模式,原型模式,混合模式,動態模式)

nod nodejs 重新 作用域 this 一次 無法 typeof 訪問

<1>工廠模式

簡單來說就是封裝後的代碼,簡單的工廠模式是很好理解的,關於它的作用,就是利用面向對象的方法,把一些對象封裝,使一些占用空間多的,重復的代碼封裝起來。實現方法非常簡單,也就是在函數內創建一個對象,給對象賦予屬性以及方法再將對象返回即可。

function creatper(name,age){

var per=new Object(); //原料

//加工

per.name=name;

per.age=age;

per.sayHi=function(){

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();

關於js的設計模式(簡單工廠模式,構造函數模式,原型模式,混合模式,動態模式)