我們將使用建構函式模式將原廠模式進行改寫。
複製代碼 代碼如下:
function Employee(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert(this.name);
};
}
var Jim = new Employee("jim", 22, "SoftWare Engineer");
var Sun = new Employee("Sun", 24, "Doctor");
Jim.sayName();
Sun.sayName();
在以上代碼中Employee函數取代了CreateEmployee函數,Employee中的代碼與CreateEmployee中的代碼不同如下:
沒有顯示的建立對象
直接將屬性和方法賦給了this對象
沒有return語句
要建立Employee類的新執行個體,必須使用new操作符,實際會經曆四個步驟:
建立一個新對象
將建構函式的範圍賦給新的對象
執行建構函式中代碼
返回新對象
以上代碼最後Jim和Sun中分別儲存著Employee的兩個不同執行個體,這兩個執行個體都有一個constructor(建構函式)屬性,該屬性指向Employee,可以做如下測試
複製代碼 代碼如下:
alert(Jim instanceof Employee); //true
alert(Sun instanceof Employee);//true
同時這兩個對象又都是Object類型的,可通過如下代碼檢測。
複製代碼 代碼如下:
alert(Jim instanceof Object); //true
alert(Sun instanceof Object);//true
建立自訂的建構函式意味著將來可以把它的執行個體標石為一種特定的類型,而這也正是建構函式模式勝過原廠模式的地方。
下面詳細講解一下建構函式:
將建構函式當做函數
建構函式與其他函數的唯一區別就在於調用它們的方式不同。但是建構函式也是函數,不存在定義建構函式的特殊文法。其實,任何函數,只有通過new來調用,那他就可以作為建構函式,例如,Employee除了以上用new方法調用外,還可以用如下方式來調用。
複製代碼 代碼如下:
//作為普通函數調用
Employee("Sun", 28, "SoftWare Engineer"); //添加到window中
window.sayName();//Sun
複製代碼 代碼如下:
//在另一個對象的範圍中調用
var o = new Object();
Employee.call(o, "Sun", 28, "SoftWare Engineer");
o.sayName();//Sum
建構函式的問題
使用建構函式的主要問題就是都要在每個實力上重新建立一遍,以上兩個對象中的sayName方法其實是不同的Function的執行個體,可以用如下方法證明:
alert(Jim.sayName == Sun.sayName);//false
但是建立兩個完成同樣任務的Function執行個體,所以我們對上面的函數進行改寫,如下
複製代碼 代碼如下:
function Employee(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName =sayName;
}
function sayName() {
alert(this.name);
}
這樣就解決了兩個函數做同一件事情的問題,但是新的問題又會出現了,這個在全域範圍中定義的函數,實際上只能被某個對象引用,而且最要命的問題是,如果對象需要定義很多方法,那麼就需要定義很多個全域函數,所以這個自訂的參考型別,就沒有任何封裝性可言了.