欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談javascript 面向?qū)ο缶幊?/h1>
 更新時間:2009年10月28日 15:00:02   作者:  
這周心血來潮,翻看了現(xiàn)在比較流行的幾個JS腳本框架的底層代碼,雖然是走馬觀花,但也受益良多,感嘆先人們的偉大……
感嘆是為了緩解嚴(yán)肅的氣氛并引出今天要講的話題,”javascript面向?qū)ο缶幊獭保酉聛?,我們圍繞面向?qū)ο蟮膸状箨P(guān)鍵字:封裝,繼承,多態(tài),展開。
封裝:javascript中創(chuàng)建對象的模式中,個人認(rèn)為通過閉包才算的上是真正意義上的封裝,所以首先我們先來簡單介紹一下閉包,看下面這個例子:
復(fù)制代碼 代碼如下:

<script type="text/javascript">
function myInfo(){
var name ="老魚",age =27;
var myInfo = "my name is" + name + "i am" + age +"years old";
function showInfo(){
alert(myInfo);
}
return showInfo;
}
var oldFish = myInfo();
oldFish();
</script>

是不是很眼熟呢?沒錯了,這其實就是一個簡單的閉包應(yīng)用了。簡單解釋一下:上面的函數(shù)myInfo中定義的變量,在它的內(nèi)嵌函數(shù)showInfo中是可訪問的(這個很好理解),但是當(dāng)我們把這個內(nèi)嵌函數(shù)的返回引用賦值給一個變量oldFish,這個時候函數(shù)showInfo是在myInfo函數(shù)體外被調(diào)用,但是同樣可以訪問到定義在函數(shù)體內(nèi)的變量。oh yeah!
總結(jié)一下閉包的原理吧:函數(shù)是運行在定義他們的作用域中而不是調(diào)用他們的作用域中。其實返回一個內(nèi)嵌函數(shù)也是創(chuàng)建閉包最常用的一種方法!
如果覺得上面的解釋太抽象的話,那么我們一起重塑上面的函數(shù),看看這樣是否層次鮮明一些:
復(fù)制代碼 代碼如下:

<script type="text/javascript">
var ioldFish = function(name,age){
var name = name,age = age;
var myInfo = "my name is" + name + "i am" + age +"years old";
return{
showInfo:function(){
alert(myInfo);
}
}
}
ioldFish("老魚",27).showInfo();
</script>

上例中的編碼風(fēng)格是ext yui中比較常見的,公私分明,一目了然。通過閉包,我們可以很方便的把一些不希望被外部直接訪問到的東西隱藏起來,你要訪問函數(shù)內(nèi)定義的變量,只能通過特定的方法才可以訪問的到,直接從外部訪問是訪問不到的,寫的挺累,饒了一圈終于轉(zhuǎn)回來了,封裝嘛,不就是把不希望被別人看到的東西隱藏起來嘛!哈哈……
上例如果轉(zhuǎn)換成JQ的風(fēng)格的話,應(yīng)該如下例所寫, 這樣的封裝模式屬于門戶大開型模式,里面定義的變量是可以被外部訪問到的(下面的例子如果你先實例化一個對象,然后在函數(shù)外部訪問對象的name或者age屬性都是可以讀取到的)當(dāng)然這種模式下我們可以設(shè)置一些”潛規(guī)則”,讓團(tuán)隊開發(fā)成員明白哪些變量是私用的,通常我們?nèi)藶榈脑谒接凶兞亢头椒ㄇ凹酉聞澗€”_”,標(biāo)識警戒訊號!從而實現(xiàn)”封裝”!
復(fù)制代碼 代碼如下:

<script type="text/javascript">
var ioldFish = function(name,age){
return ioldFish.func.init(name,age);
};
ioldFish.func = ioldFish.prototype ={
init:function(name,age){
this.name = name;
this.age = age;
return this;
},
showInfo:function(){
var info = "my name is" + this.name +"i am " +this.age+"years old";
alert(info);
}
};
ioldFish.func.init.prototype = ioldFish.func;
ioldFish(" 老 魚",27).showInfo();
//var oldFish = new ioldFish("老魚",27);
//alert(oldFish.name);
</script>

可能有人會問,哪種模式好呢?這個怎么說呢?兩種方式都有優(yōu)缺點,結(jié)合著用唄!總之一個原則,一定一定不能直接被外部對象訪問的東西,就用閉包封裝吧?!币欢ㄒ欢ā彼膫€字很深奧,不斷實踐中才能體會真諦!
繼承:提到這個的時候,要順便再補充一句:閉包封裝中的一個缺點,不利于子類的派生,所以閉包有風(fēng)險,封裝需謹(jǐn)慎!直觀起見,下面例子中創(chuàng)建對象的方式,采用”門戶大開型”模式。
在javascript中繼承一般分為三種方式:”類式繼承”,”原型繼承”,”摻元類”。下面簡單的介紹一下三類繼承方式的原理。
A.類式繼承:這個是現(xiàn)在主流框架中常用的繼承方式,看下例:
復(fù)制代碼 代碼如下:

<script type="text/javascript">
var Name = function(name){
this.name = name;
};
Name.prototype.getName = function(){
alert(this.name);
};
var Fish = function(name,age){
Name.call(this,name);
this.age = age;
};
Fish.prototype = new Name();
Fish.prototype.constructor = Fish;
Fish.prototype.showInfo = function(){
alert(this.age);
}
var ioldFish = new Fish("老魚",27);
ioldFish.getName();
</script>

上述子類Fish中并沒定義getName方法,但是子類Fish的實例對象ioldFish依然調(diào)用到了該方法,這是因為子類Fish繼承了超類Name中定義的getName方法。解釋一下,這里子類Fish的prototype指到了超類的一個實例,在子類Fish中雖然沒有申明getName方法,但是根據(jù)原型鏈原理,會向prototype指向的上一級對象中去查找是否有該方法,如果沒找到該方法,會一直搜索到最初的原型對象。這其實也就是繼承的原理了。這里特別說明一下,F(xiàn)ish.prototype.constructor = Fish;這句,由于默認(rèn)子類的prototype應(yīng)該是指向本身的,但是之前把prototype指向到了超類的實例對象,所以在這里要把它設(shè)置回來。當(dāng)然這里可以把相關(guān)代碼通過一個函數(shù)來組織起來,起到偽裝extend的作用,看如下代碼:
復(fù)制代碼 代碼如下:

function extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
}

B.原型繼承,從內(nèi)存性能上看優(yōu)于類式繼承。
復(fù)制代碼 代碼如下:

<script type="text/javascript">
function clone(object){
var F = function(){};
F.prototype = object;
return new F();
};
var Name = {
name:"who's name",
showInfo:function(){
alert(this.name);
}
};
var Fish = clone(Name);
//Fish.name = "老魚";
Fish.showInfo();
</script>

很明顯,原型繼承核心就是這個clone函數(shù),同樣是原型鏈的原理,不同的是它直接克隆超類,這樣的話子類就繼承了超類的所有屬性和方法.特別說一下,這類繼承并不需要創(chuàng)建構(gòu)造函數(shù),只需要創(chuàng)建一個對象字變量,定義相應(yīng)的屬性和方法,然后在子類中只需要通過圓點”.”符號來引用屬性和方法就可以了.
C.摻元類:把一些常用通用性比較大的方法統(tǒng)一封裝在一個函數(shù)中,然后通過下面這個函數(shù)分派給要用到這些方法的類.還可以針對不同的類,選擇性的傳遞需要的方法。
復(fù)制代碼 代碼如下:

<script type="text/javascript">
function agument(receveClass,giveClass){
if(arguments[2]){
var len = arguments.length;
for(i=2;i<len;i++){
receveClass.prototype[arguments[i]] = giveClass.prototype[arguments[i]];
}
}
else{
for(method in giveClass.prototype){
if(!receveClass.prototype[method]){
receveClass.prototype[method] = giveClass.prototype[method];
}
}
}
};
var Name = function(){};
Name.prototype ={
sayLike:function(){
alert("i like oldfish");
},
sayLove:function(){
alert("i love oldfish");
}
}
var Fish = function(){};
var ioldFish = new Fish();
agument(Fish,Name,"sayLove");
ioldFish.sayLove();
ioldFish.sayLike();
</script>

多態(tài):個人覺得這個比較抽象,很難言傳,所以下面就從重載和覆蓋兩個方面來簡單闡述一下。
重載:上面這個例子中agument函數(shù)初始帶了兩個參數(shù),但是在后面的調(diào)用中,agument(Fish,Name,”sayLove”)同樣可以帶入任意多個參數(shù),javascript的重載,是在函數(shù)中由用戶自己通過操作arguments這個屬性來實現(xiàn)的。
覆蓋:這個很簡單,就是子類中定義的方法如果與從超類中繼承過來的的方法同名,就覆蓋這個方法(這里并不是覆蓋超類中的方法,注意一下),這里就不累贅了!
最后重點著墨說一下this和執(zhí)行上下文,在前面舉的封裝例子中,this都是表示this所在的類的實例化對象本身,但是并不是千篇一律的,打個比方,通過HTML屬性定義的事件處理代碼,見如下代碼:
復(fù)制代碼 代碼如下:

<script type="text/javascript">
var Name = function(name) {
this.name = name;
this.getName = function () {
alert(this.name);
}
};
var ioldFish = new Name("老魚"),
btn = document.getElementById('btn');
btn.onclick = ioldFish.getName;
//btn.onclick = function(){ioldFish.getName.call(ioldFish)};
</script>

上例中點了按鈕以后彈出框里并沒有顯示出實例對象的屬性,這是因為this的執(zhí)行上下文已經(jīng)改變了,他現(xiàn)在所在的上下文應(yīng)該是input這個HTML標(biāo)簽,但是該標(biāo)簽又不存在getName這個屬性,所以自然無法輸出這個屬性的屬性值了!從這個例子我們不難看出:執(zhí)行上下文是在執(zhí)行時才確定的,它隨時可以變。
當(dāng)然你可以去掉上面我注釋掉的那段代碼,通過call改變this的執(zhí)行上下文,從而獲取getName方法。apply方法同樣可以實現(xiàn)改變執(zhí)行上下文的功能,不過在prototype框架中發(fā)現(xiàn)了一個更為優(yōu)美的實現(xiàn)方法bind??匆幌逻@個方法的實現(xiàn)吧,不得不感嘆先人的偉大……
復(fù)制代碼 代碼如下:

Function.prototype.bind = function(obj) {
var method = this,
temp = function() {
return method.apply(obj, arguments);
};
}

相信如果能看明白的話,您已經(jīng)可以靠這些知識點,去寫一個簡單的腳本框架了,多多實踐,相信不久的將來就能高手進(jìn)級了!如果沒看明白,也不用著急,面向?qū)ο蟊緛砭陀行┏橄?,多練?xí)練習(xí),應(yīng)該OK的了,加油……
這篇先寫到這吧,下篇文章可以和大家一起探討一下,javascript的設(shè)計模式,敬請期待。

相關(guān)文章

  • 手把手教你自己寫一個js表單驗證框架的方法

    手把手教你自己寫一個js表單驗證框架的方法

    其實我自己也就能簡單用用js而已,但是呢,相對很多初學(xué)者來說多懂了點Know How所以斗膽孟浪一下,將一些所得記錄下來,以供更多的初學(xué)者能夠知道一個東西的實現(xiàn)過程,省去在源碼里摸索的過程。
    2010-09-09
  • XRegExp 0.2: Now With Named Capture

    XRegExp 0.2: Now With Named Capture

    XRegExp 0.2: Now With Named Capture...
    2007-11-11
  • JavaScript 面向?qū)ο蟮?私有成員和公開成員

    JavaScript 面向?qū)ο蟮?私有成員和公開成員

    這節(jié)來說下JavaScript的私有成員和公開成員,雖然JavaScript沒有private和public關(guān)鍵字,但還是那句話——作為開發(fā)人員我們要有面向?qū)ο蟮乃枷耄?
    2010-05-05
  • 詳解new function(){}和function(){}() 區(qū)別分析

    詳解new function(){}和function(){}() 區(qū)別分析

    只要 new 表達(dá)式之后的 constructor 返回(return)一個引用對象(數(shù)組,對象,函數(shù)等),都將覆蓋new創(chuàng)建的匿名對象,如果返回(return)一個原始類型(無 return 時其實為 return 原始類型 undefined),那么就返回 new 創(chuàng)建的匿名對象。
    2008-03-03
  • javascript 寫類方式之七

    javascript 寫類方式之七

    dojo最新是1.3.1了,記得07年時還是0.4。文檔也漸漸多了起來,用dojo的也慢慢多了。dojo還發(fā)布了core版,壓縮后只有27kb。
    2009-07-07
  • javascript 寫類方式之一

    javascript 寫類方式之一

    這篇起,會由淺到深的分析js OO之寫類方式,大概會有5-8篇。后面陸續(xù)會分析流行庫(框架)的寫類方式。為了討論的單一性,暫不考慮類的繼承,(私有,受保護(hù))屬性或方法。
    2009-07-07
  • js面向?qū)ο?多種創(chuàng)建對象方法小結(jié)

    js面向?qū)ο?多種創(chuàng)建對象方法小結(jié)

    js面向?qū)ο?多種創(chuàng)建對象方法小結(jié),需要的朋友可以參考下
    2012-05-05
  • JS小框架 fly javascript framework

    JS小框架 fly javascript framework

    這幾天把工作中積累的東西整理成了一個小框架,分享給大家,希望對大家有用,也想聽一下大家的批評
    2009-11-11
  • js 函數(shù)調(diào)用模式小結(jié)

    js 函數(shù)調(diào)用模式小結(jié)

    在javascript中一共有四種調(diào)用模式:方法調(diào)用模式、函數(shù)調(diào)用模式、構(gòu)造器調(diào)用模式和apply調(diào)用模式。這些模式在如何初始化關(guān)鍵參數(shù)this上存在差異
    2011-12-12

最新評論