JS面向?qū)ο蠡A(chǔ)講解(工廠模式、構(gòu)造函數(shù)模式、原型模式、混合模式、動(dòng)態(tài)原型模式)
什么是面向?qū)ο螅棵嫦驅(qū)ο笫且环N思想?。◤U話(huà))。
面向?qū)ο罂梢园殉绦蛑械年P(guān)鍵模塊都視為對(duì)象,而模塊擁有屬性及方法。這樣我們?nèi)绻岩恍傩约胺椒ǚ庋b起來(lái),日后使用將非常方便,也可以避免繁瑣重復(fù)的工作。接下來(lái)將為大家講解在JS中面向?qū)ο蟮膶?shí)現(xiàn)。
工廠模式
工廠模式是軟件工程領(lǐng)域一種廣為人知的設(shè)計(jì)模式,而由于在ECMAScript中無(wú)法創(chuàng)建類(lèi),因此用函數(shù)封裝以特定接口創(chuàng)建對(duì)象。其實(shí)現(xiàn)方法非常簡(jiǎn)單,也就是在函數(shù)內(nèi)創(chuàng)建一個(gè)對(duì)象,給對(duì)象賦予屬性及方法再將對(duì)象返回即可。
function createBlog(name, url) {
var o = new Object();
o.name = name;
o.url = url;
o.sayUrl= function() {
alert(this.url);
}
return o;
}
var blog1 = createBlog('wuyuchang', 'http://www.fzitv.net/');
可以看到工廠模式的實(shí)現(xiàn)方法非常簡(jiǎn)單,解決了創(chuàng)建多個(gè)相似對(duì)象的問(wèn)題,但是工廠模式卻無(wú)從識(shí)別對(duì)象的類(lèi)型,因?yàn)槿慷际荗bject,不像Date、Array等,因此出現(xiàn)了構(gòu)造函數(shù)模式。
構(gòu)造函數(shù)模式
ECMAScript中構(gòu)造函數(shù)可以創(chuàng)建特定類(lèi)型的對(duì)象,類(lèi)似于Array、Date等原生JS的對(duì)象。其實(shí)現(xiàn)方法如下:
function Blog(name, url) {
this.name = name;
this.url = url;
this.alertUrl = function() {
alert(this.url);
}
}
var blog = new Blog('wuyuchang', 'http://www.fzitv.net/');
console.log(blog instanceof Blog); // true, 判斷blog是否是Blog的實(shí)例,即解決了工廠模式中不能
這個(gè)例子與工廠模式中除了函數(shù)名不同以外,細(xì)心的童鞋應(yīng)該發(fā)現(xiàn)許多不同之處:
函數(shù)名首寫(xiě)字母為大寫(xiě) ?。m然標(biāo)準(zhǔn)沒(méi)有嚴(yán)格規(guī)定首寫(xiě)字母為大寫(xiě),但按照慣例,構(gòu)造函數(shù)的首寫(xiě)字母用大寫(xiě)
沒(méi)有顯示的創(chuàng)建對(duì)象
直接將屬性和方法賦值給了this對(duì)象
沒(méi)有return語(yǔ)句
使用new創(chuàng)建對(duì)象
能夠識(shí)別對(duì)象(這正是構(gòu)造函數(shù)模式勝于工廠模式的地方)
構(gòu)造函數(shù)雖然好用,但也并非沒(méi)有缺點(diǎn),使用構(gòu)造函數(shù)的最大的問(wèn)題在于每次創(chuàng)建實(shí)例的時(shí)候都要重新創(chuàng)建一次方法(理論上每次創(chuàng)建對(duì)象的時(shí)候?qū)ο蟮膶傩跃煌?,而?duì)象的方法是相同的),然而創(chuàng)建兩次完全相同的方法是沒(méi)有必要的,因此,我們可以將函數(shù)移到對(duì)象外面(也許有些童鞋已經(jīng)看出缺點(diǎn),噓!)。
function Blog(name, url) {
this.name = name;
this.url = url;
this.alertUrl = alertUrl;
}
function alertUrl() {
alert(this.url);
}
var blog = new Blog('scjb51', 'http://sc.jb51.net/'),
blog2 = new Blog('jb51', 'http://www.fzitv.net/');
blog.alertUrl(); // http://sc.jb51.net/
blog2.alertUrl(); // http://www.fzitv.net/
我們將alertUrl設(shè)置成全局函數(shù),這樣一來(lái)blog與blog2訪問(wèn)的都是同一個(gè)函數(shù),可是問(wèn)題又來(lái)了,在全局作用域中定義了一個(gè)實(shí)際只想讓Blog使用的函數(shù),顯示讓全局作用域有些名副其實(shí),更讓人無(wú)法接受的是在全局作用域中定義了許多僅供特定對(duì)象使用的方法,浪費(fèi)空間不說(shuō),顯然失去了面向?qū)ο蠓庋b性了,因此可以通過(guò)原型來(lái)解決此問(wèn)題。
原型模式
我們創(chuàng)建的每個(gè)函數(shù)都有prototype(原型)屬性,這個(gè)屬性是一個(gè)指針,指向一個(gè)對(duì)象,而這個(gè)對(duì)象的用途是包含可以由特定類(lèi)型的所有實(shí)例共享的屬性和方法。使用原型對(duì)象的好處就是可以讓所有對(duì)象實(shí)例共享它所包含的屬性及方法。
function Blog() {
}
Blog.prototype.name = 'wuyuchang';
Blog.prototype.url = 'http://tools.jb51.net/';
Blog.prototype.friend = ['fr1', 'fr2', 'fr3', 'fr4'];
Blog.prototype.alertInfo = function() {
alert(this.name + this.url + this.friend );
}
// 以下為測(cè)試代碼
var blog = new Blog(),
blog2 = new Blog();
blog.alertInfo(); // wuyuchanghttp://tools.jb51.net/fr1,fr2,fr3,fr4
blog2.alertInfo(); // wuyuchanghttp://tools.jb51.net/fr1,fr2,fr3,fr4
blog.name = 'wyc1';
blog.url = 'http://***.com';
blog.friend.pop();
blog2.name = 'wyc2';
blog2.url = 'http://+++.com';
blog.alertInfo(); // wyc1http://***.comfr1,fr2,fr3
blog2.alertInfo(); // wyc2http://+++.comfr1,fr2,fr3
原型模式也不是沒(méi)有缺點(diǎn),首先,它省略了構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實(shí)例在默認(rèn)情況下都取得了相同的屬性值,這樣非常不方便,但這還是不是原型的最大問(wèn)題,原型模式的最大問(wèn)題在于共享的本性所導(dǎo)致的,由于共享,因此因此一個(gè)實(shí)例修改了引用,另一個(gè)也隨之更改了引用。因此我們通常不單獨(dú)使用原型,而是結(jié)合原型模式與構(gòu)造函數(shù)模式。
混合模式(原型模式 + 構(gòu)造函數(shù)模式)
function Blog(name, url, friend) {
this.name = name;
this.url = url;
this.friend = friend;
}
Blog.prototype.alertInfo = function() {
alert(this.name + this.url + this.friend);
}
var blog = new Blog('wuyuchang', 'http://tools.jb51.net/', ['fr1', 'fr2', 'fr3']),
blog2 = new Blog('wyc', 'http://**.com', ['a', 'b']);
blog.friend.pop();
blog.alertInfo(); // wuyuchanghttp://tools.jb51.net/fr1,fr2
blog2.alertInfo(); // wychttp://**.coma,b
混合模式中構(gòu)造函數(shù)模式用于定義實(shí)例屬性,而原型模式用于定義方法和共享屬性。每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性,但同時(shí)又共享著方法,最大限度的節(jié)省了內(nèi)存。另外這種模式還支持傳遞初始參數(shù)。優(yōu)點(diǎn)甚多。這種模式在ECMAScript中是使用最廣泛、認(rèn)同度最高的一種創(chuàng)建自定義對(duì)象的方法。
動(dòng)態(tài)原型模式
動(dòng)態(tài)原型模式將所有信息封裝在了構(gòu)造函數(shù)中,而通過(guò)構(gòu)造函數(shù)中初始化原型(僅第一個(gè)對(duì)象實(shí)例化時(shí)初始化原型),這個(gè)可以通過(guò)判斷該方法是否有效而選擇是否需要初始化原型。
function Blog(name, url) {
this.name = name;
this.url = url;
if (typeof this.alertInfo != 'function') {
// 這段代碼只執(zhí)行了一次
alert('exe time');
Blog.prototype.alertInfo = function() {
alert(thia.name + this.url);
}
}
}
var blog = new Blog('wuyuchang', 'http://tools.jb51.net'),
blog2 = new Blog('wyc', 'http:***.com');
可以看到上面的例子中只彈出一次窗,'exe time',即當(dāng)blog初始化時(shí),這樣做blog2就不在需要初始化原型,對(duì)于使用這種模式創(chuàng)建對(duì)象,可以算是perfect了。
此博文參考《JavaScript高級(jí)程序設(shè)計(jì)》第3版,但語(yǔ)言都經(jīng)過(guò)簡(jiǎn)化,例子也重寫(xiě)過(guò),如果有什么不懂的地方請(qǐng)留言回復(fù),作者將更新博客。
- JS中創(chuàng)建自定義類(lèi)型的常用模式總結(jié)【工廠模式,構(gòu)造函數(shù)模式,原型模式,動(dòng)態(tài)原型模式等】
- JavaScript創(chuàng)建對(duì)象方式總結(jié)【工廠模式、構(gòu)造函數(shù)模式、原型模式等】
- 詳解js產(chǎn)生對(duì)象的3種基本方式(工廠模式,構(gòu)造函數(shù)模式,原型模式)
- js面向?qū)ο笾R?jiàn)創(chuàng)建對(duì)象的幾種方式(工廠模式、構(gòu)造函數(shù)模式、原型模式)
- JS創(chuàng)建對(duì)象常用設(shè)計(jì)模式工廠構(gòu)造函數(shù)及原型
相關(guān)文章
JavaScript代碼輕松實(shí)現(xiàn)網(wǎng)頁(yè)內(nèi)容禁止復(fù)制(代碼簡(jiǎn)單)
有些時(shí)候我們寫(xiě)的內(nèi)容不想被別人復(fù)制,在代碼中怎么實(shí)現(xiàn)的呢?下面小編給大家介紹javascript代碼輕松實(shí)現(xiàn)網(wǎng)頁(yè)內(nèi)容禁止復(fù)制,感興趣的童鞋一起看看吧2015-10-10
詳解CocosCreator系統(tǒng)事件是怎么產(chǎn)生及觸發(fā)的
這篇文章主要介紹了CocosCreator系統(tǒng)事件是怎么產(chǎn)生及觸發(fā)的,雖然內(nèi)容不少,但是只要一點(diǎn)點(diǎn)抽絲剝繭,具體分析其內(nèi)容,就會(huì)豁然開(kāi)朗2021-04-04
javascript改變position值實(shí)現(xiàn)菜單滾動(dòng)至頂部后固定
現(xiàn)在很多網(wǎng)站都有這樣的一個(gè)效果,當(dāng)頁(yè)面滾動(dòng)到一定高度時(shí),菜單欄會(huì)固定在頁(yè)面頂部;該效果在 ie6 下不支持,因?yàn)閕e6不支持 position:fixed,效果很不錯(cuò),感興趣的朋友可以了解下啊2013-01-01
javascript過(guò)濾數(shù)組重復(fù)元素的實(shí)現(xiàn)方法
這篇文章主要介紹了javascript過(guò)濾數(shù)組重復(fù)元素的實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2017-05-05
js瀏覽器滾動(dòng)條卷去的高度scrolltop(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇js瀏覽器滾動(dòng)條卷去的高度scrolltop(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
使用javascript獲取flash加載的百分比的實(shí)現(xiàn)代碼
使用javascript獲取flash加載的百分比的實(shí)現(xiàn)代碼,方便flash小游戲判斷頁(yè)面,提高用戶(hù)體驗(yàn)。2011-05-05
如何使用JavaScript和XLSX.js將數(shù)據(jù)導(dǎo)出為Excel文件

