JavaScript之自定義類型
更新時(shí)間:2012年05月04日 00:39:14 作者:
在JavaScript中,創(chuàng)建一個(gè)具有自定義屬性和方法的對(duì)象有很多種模式,下面一一進(jìn)行介紹
1、直接創(chuàng)建模式。這是最簡(jiǎn)單也是最直接的一種模式,首先創(chuàng)建一個(gè)引用類型的對(duì)象,然后為其添加自定義屬性和方法。示例代碼如下:
var person = new Object();
person.name = "Sam";
person.age = 16;
person.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
person.speak();
可以看到,上面創(chuàng)建了一個(gè)Object類型的對(duì)象,然后為其添加了name和age屬性以及一個(gè)speak方法。直接創(chuàng)建模式雖然簡(jiǎn)單,但其缺點(diǎn)是顯而易見(jiàn)的:當(dāng)我們需要?jiǎng)?chuàng)建許多相同的對(duì)象時(shí),每次都要重復(fù)編寫(xiě)代碼。為了解決這個(gè)問(wèn)題,我們可以將創(chuàng)建對(duì)象的過(guò)程進(jìn)行封裝,于是便有了下面的工廠模式。
2、工廠模式。工廠模式是程序設(shè)計(jì)中一種常用的設(shè)計(jì)模式,它主要是將創(chuàng)建對(duì)象的過(guò)程進(jìn)行了封裝,示例代碼如下:
function createPerson(name, age){
var person = new Object();
person.name = name;
person.age = age;
person.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
return person;
}
var person1 = createPerson("Sam", 16);
var person2 = createPerson("Jack", 18);
使用工廠模式后,創(chuàng)建相同類型的對(duì)象變得簡(jiǎn)單了。但工廠模式?jīng)]有解決對(duì)象識(shí)別的問(wèn)題,即我們無(wú)法確定創(chuàng)建的對(duì)象的具體類型。有過(guò)面向?qū)ο缶幊探?jīng)驗(yàn)的開(kāi)發(fā)人員都知道,對(duì)象的創(chuàng)建應(yīng)當(dāng)基于類,有了具體的自定義類,再來(lái)創(chuàng)建該類的對(duì)象。幸好,在JavaScript中,我們可以通過(guò)構(gòu)造函數(shù)模式來(lái)模擬一個(gè)類。
3、構(gòu)造函數(shù)模式。構(gòu)造函數(shù)和普通函數(shù)沒(méi)有任何區(qū)別。任何普通函數(shù)都可以作為構(gòu)造函數(shù),只要使用new操作符即可;任何構(gòu)造函數(shù)也都可以作為普通函數(shù)來(lái)調(diào)用。只不過(guò)在JavaScript中,有一個(gè)約定,就是用作構(gòu)造函數(shù)的函數(shù)名需要首字母大寫(xiě)。示例代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
this.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
}
var person1 = new Person("Sam", 16);
var person2 = new Person("Jack", 18);
可以看到,在構(gòu)造函數(shù)內(nèi)部,我們使用了this來(lái)添加屬性和方法,那么,這個(gè)this是指什么呢?當(dāng)我們創(chuàng)建了一個(gè)Person的對(duì)象時(shí),this即是指這個(gè)創(chuàng)建的對(duì)象。現(xiàn)在,我們可以識(shí)別出對(duì)象person1和person2的具體類型了。使用alert(person1 instanceOf Person)后可以發(fā)現(xiàn),輸出的值為true。但構(gòu)造函數(shù)模式也有自己的缺點(diǎn),就是構(gòu)造函數(shù)內(nèi)聲明的方法在每次創(chuàng)建新對(duì)象時(shí)都會(huì)重新創(chuàng)建(在JavaScript中,函數(shù)也是對(duì)象)。也就是說(shuō),構(gòu)造函數(shù)內(nèi)的方法是與對(duì)象綁定的,而不是與類綁定的。下面代碼的輸出可以驗(yàn)證我們的推斷。
alert(person1.speak == person2.speak); // false 解決這個(gè)缺點(diǎn)的一種比較簡(jiǎn)單的方法就是將函數(shù)的聲明放到構(gòu)造函數(shù)的外面,即:
function Person(name, age){
this.name = name;
this.age = age;
this.speak = speak;
}
function speak(){
alert(this.name + "is " + this.age + "years old");
}
var person1 = new Person("Sam", 16);
var person2 = new Person("Jack", 18);
alert(person1.speak == person2.speak); // true
問(wèn)題解決了,但這種方法又帶來(lái)了新的問(wèn)題。首先,函數(shù)speak是在全局作用域中聲明的,但它卻只能被用于Person構(gòu)造函數(shù),放在全局作用域中有被誤用的風(fēng)險(xiǎn);其次,如果一個(gè)自定義類型有很多的方法,則需要聲明很多的全局函數(shù),這既將導(dǎo)致全局作用域的污染,也不利于代碼的封裝。那么,有沒(méi)有什么辦法能讓自定義類型的方法成為與類綁定的,又不污染全局作用域呢?答案是使用原型模式。
4、原型模式。在我們聲明一個(gè)新的函數(shù)后,該函數(shù)(在JavaScript中,函數(shù)也是對(duì)象)就會(huì)擁有一個(gè)prototype的屬性。prototype是一個(gè)對(duì)象,表示會(huì)被該函數(shù)創(chuàng)建的所有對(duì)象擁有的公共屬性和方法。示例代碼如下:
function Person(){}
Person.prototype.name="Sam";
Person.prototype.age=16;
Person.prototype.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
var person1 = new Person();
person1.speak();
var person2 = new Person();
alert(person1.speak == person2.speak); // true
可以看到,雖然構(gòu)造函數(shù)內(nèi)沒(méi)有聲明speak方法,但我們創(chuàng)建的對(duì)象person1還是能調(diào)用speak方法,這是因?yàn)镴avaScript有一個(gè)搜索規(guī)則,先搜索實(shí)例屬性和方法,找到則返回;如果沒(méi)找到,則再到prototype中去搜索。原型模式使得方法是與類相關(guān)的,并且沒(méi)有污染全局作用域,但其也有自身的缺點(diǎn):一是所有屬性也都與類相關(guān),這意味著所有對(duì)象共享一份屬性,這顯然是不合理的;二是沒(méi)有辦法向構(gòu)造函數(shù)傳入初始化數(shù)據(jù)了。解決的方法很簡(jiǎn)單,就是混合使用構(gòu)造函數(shù)模式和原型模式。
5、組合模式。示例代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
var person1 = new Person();
person1.speak();
var person2 = new Person();
alert(person1.speak == person2.speak); // true
不難發(fā)現(xiàn),組合模式實(shí)現(xiàn)了我們的所有需求,這也是目前應(yīng)用得比較廣泛的一種模式。有面向?qū)ο缶幊探?jīng)驗(yàn)的開(kāi)發(fā)人員可能會(huì)覺(jué)得將prototype的聲明放在構(gòu)造函數(shù)外面有點(diǎn)別扭,那么能否將其放到構(gòu)造函數(shù)里去呢?答案是肯定的,使用動(dòng)態(tài)組合模式即可。
6、動(dòng)態(tài)組合模式。其原理就是先判斷原型中的某個(gè)屬性或方法是不是已經(jīng)聲明過(guò),如果沒(méi)有聲明,則聲明整個(gè)原型;否則,什么也不用做。示例代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
if (Person.prototype.speak == "undefined"){
Person.prototype.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
}
}
復(fù)制代碼 代碼如下:
var person = new Object();
person.name = "Sam";
person.age = 16;
person.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
person.speak();
可以看到,上面創(chuàng)建了一個(gè)Object類型的對(duì)象,然后為其添加了name和age屬性以及一個(gè)speak方法。直接創(chuàng)建模式雖然簡(jiǎn)單,但其缺點(diǎn)是顯而易見(jiàn)的:當(dāng)我們需要?jiǎng)?chuàng)建許多相同的對(duì)象時(shí),每次都要重復(fù)編寫(xiě)代碼。為了解決這個(gè)問(wèn)題,我們可以將創(chuàng)建對(duì)象的過(guò)程進(jìn)行封裝,于是便有了下面的工廠模式。
2、工廠模式。工廠模式是程序設(shè)計(jì)中一種常用的設(shè)計(jì)模式,它主要是將創(chuàng)建對(duì)象的過(guò)程進(jìn)行了封裝,示例代碼如下:
復(fù)制代碼 代碼如下:
function createPerson(name, age){
var person = new Object();
person.name = name;
person.age = age;
person.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
return person;
}
var person1 = createPerson("Sam", 16);
var person2 = createPerson("Jack", 18);
使用工廠模式后,創(chuàng)建相同類型的對(duì)象變得簡(jiǎn)單了。但工廠模式?jīng)]有解決對(duì)象識(shí)別的問(wèn)題,即我們無(wú)法確定創(chuàng)建的對(duì)象的具體類型。有過(guò)面向?qū)ο缶幊探?jīng)驗(yàn)的開(kāi)發(fā)人員都知道,對(duì)象的創(chuàng)建應(yīng)當(dāng)基于類,有了具體的自定義類,再來(lái)創(chuàng)建該類的對(duì)象。幸好,在JavaScript中,我們可以通過(guò)構(gòu)造函數(shù)模式來(lái)模擬一個(gè)類。
3、構(gòu)造函數(shù)模式。構(gòu)造函數(shù)和普通函數(shù)沒(méi)有任何區(qū)別。任何普通函數(shù)都可以作為構(gòu)造函數(shù),只要使用new操作符即可;任何構(gòu)造函數(shù)也都可以作為普通函數(shù)來(lái)調(diào)用。只不過(guò)在JavaScript中,有一個(gè)約定,就是用作構(gòu)造函數(shù)的函數(shù)名需要首字母大寫(xiě)。示例代碼如下:
復(fù)制代碼 代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
this.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
}
var person1 = new Person("Sam", 16);
var person2 = new Person("Jack", 18);
可以看到,在構(gòu)造函數(shù)內(nèi)部,我們使用了this來(lái)添加屬性和方法,那么,這個(gè)this是指什么呢?當(dāng)我們創(chuàng)建了一個(gè)Person的對(duì)象時(shí),this即是指這個(gè)創(chuàng)建的對(duì)象。現(xiàn)在,我們可以識(shí)別出對(duì)象person1和person2的具體類型了。使用alert(person1 instanceOf Person)后可以發(fā)現(xiàn),輸出的值為true。但構(gòu)造函數(shù)模式也有自己的缺點(diǎn),就是構(gòu)造函數(shù)內(nèi)聲明的方法在每次創(chuàng)建新對(duì)象時(shí)都會(huì)重新創(chuàng)建(在JavaScript中,函數(shù)也是對(duì)象)。也就是說(shuō),構(gòu)造函數(shù)內(nèi)的方法是與對(duì)象綁定的,而不是與類綁定的。下面代碼的輸出可以驗(yàn)證我們的推斷。
alert(person1.speak == person2.speak); // false 解決這個(gè)缺點(diǎn)的一種比較簡(jiǎn)單的方法就是將函數(shù)的聲明放到構(gòu)造函數(shù)的外面,即:
復(fù)制代碼 代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
this.speak = speak;
}
function speak(){
alert(this.name + "is " + this.age + "years old");
}
var person1 = new Person("Sam", 16);
var person2 = new Person("Jack", 18);
alert(person1.speak == person2.speak); // true
問(wèn)題解決了,但這種方法又帶來(lái)了新的問(wèn)題。首先,函數(shù)speak是在全局作用域中聲明的,但它卻只能被用于Person構(gòu)造函數(shù),放在全局作用域中有被誤用的風(fēng)險(xiǎn);其次,如果一個(gè)自定義類型有很多的方法,則需要聲明很多的全局函數(shù),這既將導(dǎo)致全局作用域的污染,也不利于代碼的封裝。那么,有沒(méi)有什么辦法能讓自定義類型的方法成為與類綁定的,又不污染全局作用域呢?答案是使用原型模式。
4、原型模式。在我們聲明一個(gè)新的函數(shù)后,該函數(shù)(在JavaScript中,函數(shù)也是對(duì)象)就會(huì)擁有一個(gè)prototype的屬性。prototype是一個(gè)對(duì)象,表示會(huì)被該函數(shù)創(chuàng)建的所有對(duì)象擁有的公共屬性和方法。示例代碼如下:
復(fù)制代碼 代碼如下:
function Person(){}
Person.prototype.name="Sam";
Person.prototype.age=16;
Person.prototype.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
var person1 = new Person();
person1.speak();
var person2 = new Person();
alert(person1.speak == person2.speak); // true
可以看到,雖然構(gòu)造函數(shù)內(nèi)沒(méi)有聲明speak方法,但我們創(chuàng)建的對(duì)象person1還是能調(diào)用speak方法,這是因?yàn)镴avaScript有一個(gè)搜索規(guī)則,先搜索實(shí)例屬性和方法,找到則返回;如果沒(méi)找到,則再到prototype中去搜索。原型模式使得方法是與類相關(guān)的,并且沒(méi)有污染全局作用域,但其也有自身的缺點(diǎn):一是所有屬性也都與類相關(guān),這意味著所有對(duì)象共享一份屬性,這顯然是不合理的;二是沒(méi)有辦法向構(gòu)造函數(shù)傳入初始化數(shù)據(jù)了。解決的方法很簡(jiǎn)單,就是混合使用構(gòu)造函數(shù)模式和原型模式。
5、組合模式。示例代碼如下:
復(fù)制代碼 代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
var person1 = new Person();
person1.speak();
var person2 = new Person();
alert(person1.speak == person2.speak); // true
不難發(fā)現(xiàn),組合模式實(shí)現(xiàn)了我們的所有需求,這也是目前應(yīng)用得比較廣泛的一種模式。有面向?qū)ο缶幊探?jīng)驗(yàn)的開(kāi)發(fā)人員可能會(huì)覺(jué)得將prototype的聲明放在構(gòu)造函數(shù)外面有點(diǎn)別扭,那么能否將其放到構(gòu)造函數(shù)里去呢?答案是肯定的,使用動(dòng)態(tài)組合模式即可。
6、動(dòng)態(tài)組合模式。其原理就是先判斷原型中的某個(gè)屬性或方法是不是已經(jīng)聲明過(guò),如果沒(méi)有聲明,則聲明整個(gè)原型;否則,什么也不用做。示例代碼如下:
復(fù)制代碼 代碼如下:
function Person(name, age){
this.name = name;
this.age = age;
if (Person.prototype.speak == "undefined"){
Person.prototype.speak = function(){
alert(this.name + "is " + this.age + "years old");
}
}
}
您可能感興趣的文章:
- Javascript 自定義類型方法小結(jié)
- JavaScript實(shí)現(xiàn)與使用發(fā)布/訂閱模式詳解
- JavaScript設(shè)計(jì)模式之裝飾者模式實(shí)例詳解
- JavaScript設(shè)計(jì)模式之享元模式實(shí)例詳解
- JavaScript設(shè)計(jì)模式之觀察者模式實(shí)例詳解
- JavaScript設(shè)計(jì)模式之命令模式實(shí)例分析
- JavaScript設(shè)計(jì)模式之責(zé)任鏈模式實(shí)例分析
- JavaScript設(shè)計(jì)模式之代理模式實(shí)例分析
- JavaScript常見(jiàn)繼承模式實(shí)例小結(jié)
- JS中創(chuàng)建自定義類型的常用模式總結(jié)【工廠模式,構(gòu)造函數(shù)模式,原型模式,動(dòng)態(tài)原型模式等】
相關(guān)文章
點(diǎn)擊按鈕彈出模態(tài)框的一系列操作代碼實(shí)例
這篇文章主要介紹了js彈出模態(tài)框方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03關(guān)于IE只能嵌套27層表格的說(shuō)法證明
關(guān)于IE只能嵌套27層表格的說(shuō)法證明...2006-11-11動(dòng)態(tài)創(chuàng)建樣式表在各瀏覽器中的差異測(cè)試代碼
對(duì)于標(biāo)準(zhǔn)瀏覽器,直接使用css.innerHTML也可以修改HTMLStyleElement的css規(guī)則2011-09-09JS中類的靜態(tài)方法,靜態(tài)變量,實(shí)例方法,實(shí)例變量區(qū)別與用法實(shí)例分析
這篇文章主要介紹了JS中類的靜態(tài)方法,靜態(tài)變量,實(shí)例方法,實(shí)例變量區(qū)別與用法,結(jié)合實(shí)例形式詳細(xì)分析了JS中類的靜態(tài)方法,靜態(tài)變量,實(shí)例方法,實(shí)例變量相關(guān)功能、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2020-03-03javascript中的void運(yùn)算符語(yǔ)法及使用介紹
void是javascript中的一個(gè)操作符,void會(huì)計(jì)算表達(dá)式的值,但是會(huì)丟棄表達(dá)式的返回值接下來(lái)將詳細(xì)介紹下,感興趣的你可以參考下或許對(duì)你有所幫助2013-03-03ExpressJS使用express-ws的實(shí)例詳解
這篇文章主要介紹了ExpressJS使用express-ws的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09快速查找數(shù)組中的某個(gè)元素并返回下標(biāo)示例
最近在寫(xiě)jquery的combobox插件時(shí)遇到效率問(wèn)題,再加上jquery選擇器的類帥選,導(dǎo)致效率很慢,采用以下方式二,可以輕松解決此問(wèn)題2013-09-09