在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 淺談 javascript 面向?qū)ο缶幊?/span>
淺談 JavaScript 之事件綁定
淺談 javascript 中字符串 String 與數(shù)組 Array
淺談 javascript 中基本包裝類型
淺談 JavaScript Math 和 Number 對(duì)象
淺談 Javascript 的靜態(tài)屬性和原型屬性
淺談 JavaScript 中定義變量時(shí)有無(wú) var 聲明的區(qū)別
淺談 JavaScript Array 對(duì)象
淺談 JavaScript 函數(shù)參數(shù)的可修改性問題
淺談 javascript 中的 instanceof 和 typeof
淺談 JavaScript 中 Date (日期對(duì)象),Math 對(duì)象
淺談 Javascript 執(zhí)行順序
淺談 javascript 函數(shù)屬性和方法
淺談 JavaScript 中面向?qū)ο蠹夹g(shù)的模擬
淺談 javascript 的原型繼承
淺談 javascript 事件取消和阻止冒泡
根據(jù)一段代碼淺談 Javascript 閉包
淺談 Javascript 面向?qū)ο缶幊?/span>
淺談 javascript 六種數(shù)據(jù)類型以及特殊注意點(diǎn)
淺談 Javascript 變量作用域問題
淺談 javascript 函數(shù)內(nèi)部屬性
淺談 javascript 中自定義模版
淺談 JavaScript 字符集
淺談 javascript 面向?qū)ο缶幊?/span>
淺談 JavaScript 框架分類
淺談 JavaScript 中的 Math.atan() 方法的使用
淺談 Javascript 數(shù)組與字典
淺談 JavaScript 數(shù)據(jù)類型及轉(zhuǎn)換
淺談 javascript 的調(diào)試
淺談 Javascript 嵌套函數(shù)及閉包
淺談 javascript 回調(diào)函數(shù)
淺談 JavaScript Date 日期和時(shí)間對(duì)象
淺談 Javascript 中的 Function 與 Object
淺談 JavaScript 數(shù)據(jù)類型
淺談 javascript 中 this 在事件中的應(yīng)用
淺談 javascript 中的閉包
淺談 javascript 函數(shù)劫持
淺談 Javascript 中深復(fù)制
淺談 JavaScript 函數(shù)節(jié)流
淺談 JavaScript 中的 String 對(duì)象常用方法
淺談 JavaScript 事件的屬性列表
淺談 JavaScript 函數(shù)與棧
淺談 JavaScript 的事件
淺談 javascript 中的作用域
淺談 JavaScript 的執(zhí)行效率
淺談 Javascript 事件模擬
淺談 JavaScript function 函數(shù)種類
淺談 javascript 歸并方法
淺談 javascript 迭代方法
淺談 JavaScript 編程語(yǔ)言的編碼規(guī)范
淺談 JavaScript 實(shí)現(xiàn)面向?qū)ο笾械念?/span>
淺談 Javascript 鼠標(biāo)和滾輪事件
淺談 Javascript Base64 加密解密
淺談 Javascript 中勻速運(yùn)動(dòng)的停止條件
淺談 javascript 實(shí)現(xiàn)八大排序
淺談 javascript 的分號(hào)的使用
淺談 javascript 中 createElement 事件
淺談 javascript 的數(shù)據(jù)類型檢測(cè)
淺談 javascript 對(duì)象模型和 function 對(duì)象
淺談 Javascript 如何實(shí)現(xiàn)勻速運(yùn)動(dòng)
淺談 JavaScript 字符串與數(shù)組
淺談 javascript 面向?qū)ο蟪绦蛟O(shè)計(jì)
淺談 Javascript 事件處理程序的幾種方式

淺談 javascript 面向?qū)ο缶幊?/h1>

感嘆是為了緩解嚴(yán)肅的氣氛并引出今天要講的話題,”javascript 面向?qū)ο缶幊獭?,接下?lái),我們圍繞面向?qū)ο蟮膸状箨P(guān)鍵字:封裝,繼承,多態(tài),展開。

封裝:javascript 中創(chuàng)建對(duì)象的模式中,個(gè)人認(rèn)為通過(guò)閉包才算的上是真正意義上的封裝,所以首先我們先來(lái)簡(jiǎn)單介紹一下閉包,看下面這個(gè)例子:

<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>  

是不是很眼熟呢?沒錯(cuò)了,這其實(shí)就是一個(gè)簡(jiǎn)單的閉包應(yīng)用了。簡(jiǎn)單解釋一下:上面的函數(shù) myInfo 中定義的變量,在它的內(nèi)嵌函數(shù) showInfo 中是可訪問的(這個(gè)很好理解),但是當(dāng)我們把這個(gè)內(nèi)嵌函數(shù)的返回引用賦值給一個(gè)變量 oldFish,這個(gè)時(shí)候函數(shù) showInfo 是在 myInfo 函數(shù)體外被調(diào)用,但是同樣可以訪問到定義在函數(shù)體內(nèi)的變量。oh yeah!

總結(jié)一下閉包的原理吧:函數(shù)是運(yùn)行在定義他們的作用域中而不是調(diào)用他們的作用域中。其實(shí)返回一個(gè)內(nèi)嵌函數(shù)也是創(chuàng)建閉包最常用的一種方法!

如果覺得上面的解釋太抽象的話,那么我們一起重塑上面的函數(shù),看看這樣是否層次鮮明一些:

<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 中比較常見的,公私分明,一目了然。通過(guò)閉包,我們可以很方便的把一些不希望被外部直接訪問到的東西隱藏起來(lái),你要訪問函數(shù)內(nèi)定義的變量,只能通過(guò)特定的方法才可以訪問的到,直接從外部訪問是訪問不到的,寫的挺累,饒了一圈終于轉(zhuǎn)回來(lái)了,封裝嘛,不就是把不希望被別人看到的東西隱藏起來(lái)嘛!哈哈……

上例如果轉(zhuǎn)換成 JQ 的風(fēng)格的話,應(yīng)該如下例所寫, 這樣的封裝模式屬于門戶大開型模式,里面定義的變量是可以被外部訪問到的(下面的例子如果你先實(shí)例化一個(gè)對(duì)象,然后在函數(shù)外部訪問對(duì)象的 name 或者 age 屬性都是可以讀取到的)當(dāng)然這種模式下我們可以設(shè)置一些” 潛規(guī)則”,讓團(tuán)隊(duì)開發(fā)成員明白哪些變量是私用的,通常我們?nèi)藶榈脑谒接凶兞亢头椒ㄇ凹酉聞澗€”_”,標(biāo)識(shí)警戒訊號(hào)!從而實(shí)現(xiàn)” 封裝”!

<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>  

可能有人會(huì)問,哪種模式好呢?這個(gè)怎么說(shuō)呢??jī)煞N方式都有優(yōu)缺點(diǎn),結(jié)合著用唄!總之一個(gè)原則,一定一定不能直接被外部對(duì)象訪問的東西,就用閉包封裝吧?!?一定一定” 四個(gè)字很深?yuàn)W,不斷實(shí)踐中才能體會(huì)真諦!

繼承:提到這個(gè)的時(shí)候,要順便再補(bǔ)充一句:閉包封裝中的一個(gè)缺點(diǎn),不利于子類的派生,所以閉包有風(fēng)險(xiǎn),封裝需謹(jǐn)慎!直觀起見,下面例子中創(chuàng)建對(duì)象的方式,采用” 門戶大開型” 模式。

在 javascript 中繼承一般分為三種方式:” 類式繼承”,” 原型繼承”,” 摻元類”。下面簡(jiǎn)單的介紹一下三類繼承方式的原理。

A. 類式繼承:這個(gè)是現(xiàn)在主流框架中常用的繼承方式,看下例:

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

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

B. 原型繼承,從內(nèi)存性能上看優(yōu)于類式繼承。

<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>  

很明顯,原型繼承核心就是這個(gè) clone 函數(shù),同樣是原型鏈的原理,不同的是它直接克隆超類,這樣的話子類就繼承了超類的所有屬性和方法。特別說(shuō)一下,這類繼承并不需要?jiǎng)?chuàng)建構(gòu)造函數(shù),只需要?jiǎng)?chuàng)建一個(gè)對(duì)象字變量,定義相應(yīng)的屬性和方法,然后在子類中只需要通過(guò)圓點(diǎn)”.” 符號(hào)來(lái)引用屬性和方法就可以了。

C. 摻元類:把一些常用通用性比較大的方法統(tǒng)一封裝在一個(gè)函數(shù)中,然后通過(guò)下面這個(gè)函數(shù)分派給要用到這些方法的類。還可以針對(duì)不同的類,選擇性的傳遞需要的方法。

<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):個(gè)人覺得這個(gè)比較抽象,很難言傳,所以下面就從重載和覆蓋兩個(gè)方面來(lái)簡(jiǎn)單闡述一下。

重載:上面這個(gè)例子中 agument 函數(shù)初始帶了兩個(gè)參數(shù),但是在后面的調(diào)用中,agument(Fish,Name,”sayLove”) 同樣可以帶入任意多個(gè)參數(shù),javascript 的重載,是在函數(shù)中由用戶自己通過(guò)操作 arguments 這個(gè)屬性來(lái)實(shí)現(xiàn)的。

覆蓋:這個(gè)很簡(jiǎn)單,就是子類中定義的方法如果與從超類中繼承過(guò)來(lái)的的方法同名,就覆蓋這個(gè)方法(這里并不是覆蓋超類中的方法,注意一下),這里就不累贅了!

最后重點(diǎn)著墨說(shuō)一下 this 和執(zhí)行上下文,在前面舉的封裝例子中,this 都是表示 this 所在的類的實(shí)例化對(duì)象本身,但是并不是千篇一律的,打個(gè)比方,通過(guò) HTML 屬性定義的事件處理代碼,見如下代碼:

<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>  

上例中點(diǎn)了按鈕以后彈出框里并沒有顯示出實(shí)例對(duì)象的屬性,這是因?yàn)?this 的執(zhí)行上下文已經(jīng)改變了,他現(xiàn)在所在的上下文應(yīng)該是 input 這個(gè) HTML 標(biāo)簽,但是該標(biāo)簽又不存在 getName 這個(gè)屬性,所以自然無(wú)法輸出這個(gè)屬性的屬性值了!從這個(gè)例子我們不難看出:執(zhí)行上下文是在執(zhí)行時(shí)才確定的,它隨時(shí)可以變。

當(dāng)然你可以去掉上面我注釋掉的那段代碼,通過(guò) call 改變 this 的執(zhí)行上下文,從而獲取 getName 方法。apply 方法同樣可以實(shí)現(xiàn)改變執(zhí)行上下文的功能,不過(guò)在 prototype 框架中發(fā)現(xiàn)了一個(gè)更為優(yōu)美的實(shí)現(xiàn)方法 bind??匆幌逻@個(gè)方法的實(shí)現(xiàn)吧,不得不感嘆先人的偉大……

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

相信如果能看明白的話,您已經(jīng)可以靠這些知識(shí)點(diǎn),去寫一個(gè)簡(jiǎn)單的腳本框架了,多多實(shí)踐,相信不久的將來(lái)就能高手進(jìn)級(jí)了!如果沒看明白,也不用著急,面向?qū)ο蟊緛?lái)就有些抽象,多練習(xí)練習(xí),應(yīng)該 OK 的了,加油……

這篇先寫到這吧,下篇文章可以和大家一起探討一下,javascript 的設(shè)計(jì)模式,敬請(qǐng)期待。