javascript 中對(duì)象的繼承〔轉(zhuǎn)貼〕
更新時(shí)間:2007年01月22日 00:00:00 作者:
1、關(guān)于javascript的apply和call函數(shù)
prototype.js中用了大量的apply和call函數(shù),不注意會(huì)造成理解偏差。
官方解釋:應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
apply與call的區(qū)別是第二個(gè)參數(shù)不同。apply是 數(shù)組或者arguments 對(duì)象。而call是逗號(hào)隔開的任何類型。
apply,call方法最讓人混淆的地方也是apply,call的特色。但最好不要濫用。
能改變調(diào)用函數(shù)的對(duì)象。如下例,函數(shù)中用到this關(guān)鍵字,這時(shí)候this代表的是apply,call函數(shù)的第一個(gè)參數(shù)。
<script src="prototype1.3.1.js"></script>
<input type="text" id="myText" value="input text">
<script>
function Obj(){
this.value="對(duì)象!";
}
var value="global 變量";
function Fun1(){
alert(this.value);
}
window.Fun1();
Fun1.apply(window);
Fun1.apply($('myText'));
Fun1.apply(new Obj());
</script>
2、關(guān)于閉包
prototype.js在Class.create,bind等中用到j(luò)avascript的閉包特色。但整體上prototype.js對(duì)于強(qiáng)大的閉包特性用的不多。大家可以參閱我翻譯的篇文章了解閉包。
3、讓我比較反感的兩個(gè)方法
(1)
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
很討厭用別的語言的風(fēng)格來寫javascript。用這個(gè)方法構(gòu)造自定義類 并沒有覺得有多方便,減少代碼行數(shù),只會(huì)讓人難理解,多定義一個(gè)initialize方法。
其實(shí)討厭這條有些牽強(qiáng),不過修改Object的原型對(duì)象就有點(diǎn)過分了。
(2)Object.prototype.extend
先不過你取個(gè)extend的名字會(huì)讓熟悉java的人引起的歧義。修改Object的prototype就說不過去了。不知道作者是怎么考慮的。當(dāng)你for in循環(huán)對(duì)象是,麻煩就來了??赡苡腥藭?huì)問你for in干嗎。 我一個(gè)項(xiàng)目中既用了DWR,也用了prototype.js,dwr返回的javascript對(duì)象都多了個(gè)exetend屬性,還得特殊處理。
以前我比較過dojo和prototype.js中繼承的實(shí)現(xiàn),現(xiàn)在我明白個(gè)道理。對(duì)于javascript這種沒有靜態(tài)類型檢查,語法寬松的語言來講,如果你選擇了某個(gè)js類庫,那你也必須適應(yīng)作者寫javascript的風(fēng)格。prototype.js的作者對(duì)extend的使用爐火純青,如果我們不當(dāng)它只是個(gè)屬性拷貝的函數(shù)的話,多讀讀prototype.js的代碼是好的。
4、關(guān)于函數(shù)的綁定
類庫提供了Function.prototype.bind Function.prototype.bindAsEventListener兩個(gè)方法。首先我們從概念上解釋一個(gè)這兩個(gè)方法。
任何一個(gè)函數(shù)都可以調(diào)用這兩個(gè)方法;參數(shù)的是javascript對(duì)象或網(wǎng)頁上元素對(duì)象;返回類型是個(gè)函數(shù)對(duì)象。
本來我就是個(gè)函數(shù),返回還是函數(shù),到這兩個(gè)函數(shù)有什么不同呢??磳?shí)現(xiàn)代碼,關(guān)鍵還是apply\call函數(shù)的代碼。其實(shí)這里只是轉(zhuǎn)化了一下方法調(diào)用的對(duì)象。
<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="asf" value=1> Test
<script>
var CheckboxWatcher = Class.create();
CheckboxWatcher.prototype = {
initialize: function(chkBox, message) {
this.chkBox = $(chkBox);
this.message = message;
this.chkBox.onclick = this.showMessage.bindAsEventListener(this);
},
showMessage: function(evt) {
alert(this.message + ' (' + evt.type + ')');
}
};
new CheckboxWatcher('myChk','message!!!!');
//$('myChk').onclick=function(){};
</script>
這是 https://compdoc2cn.dev.java.net/ 上舉的例子,個(gè)人感覺沒什么意思,反而讓我對(duì)bind,bindAsEventListener有些反感。(javascript就是這樣,明明大家都知道的語法,但寫出來的代碼差別確很大)
看下面代碼:
<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="chk" value=1> Test
<script>
function Class(){
this.name="class";
}
Class.prototype.getName=function(){
alert(this.name);
}
var obj=new Class();
//$('myChk').onclick=obj.getName;
$('myChk').onclick=obj.getName.bind(obj);
//$('myChk').onclick=obj.getName.bind($('myChk'));
</script>
從上面代碼可以看出bind/bindAsEventListener只是包裝了一下apply/call方法,改變方法的調(diào)用對(duì)象。如例子,你可以把obj.getName方法轉(zhuǎn)化成任何對(duì)象調(diào)用,并且把方法讓表單元素觸發(fā)。(bind和bindAsEventListener之間只是返回函數(shù)的參數(shù)不同)
這兩個(gè)方法也可以用在對(duì)象之間的方法重用,實(shí)現(xiàn)類似繼承方法的概念??匆韵麓a,其實(shí)是比較無聊的。
<script src="prototype1.3.1.js"></script>
<script>
function Class1(name){
this.name=name;
}
Class1.prototype.getName=function(){
alert(this.name);
}
function Class2(name){
this.name=name;
this.getName=Class1.prototype.getName.bind(this);
}
var obj1=new Class2("yql");
obj1.getName();
var obj2=new Object();
obj2.name="zkj";
obj2.fun=Class1.prototype.getName.bind(obj2);
obj2.fun();
</script>
我從來沒讀過prototype.js的擴(kuò)展項(xiàng)目代碼,也不知道bind..的最佳實(shí)踐,一起挖掘吧。但你絕對(duì)不要把bind/bindAsEventListener從綁定的詞義上來理解,可能會(huì)讓你更加迷惑。從apply/call理解本質(zhì)。應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
5、關(guān)于事件的注冊(cè)
<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="chk" value=1> Test
<script>
Event.observe(myChk, 'click', showMessage, false);
//$('myChk').onclick=showMessage;
//$('myChk').onclick=showMessage.bind();
$('myChk').onclick=showMessage.bind($('myChk'));
function showMessage() {
alert(this.value);
}
</script>
執(zhí)行上面代碼,你就能明白Event.observe與bind/bindAsEventListener之間的區(qū)別:
(1) 顯然Event.observe有限制,只能處理簡(jiǎn)單的函數(shù),并函數(shù)中不能有this之類的東西。
(2)Event.observe內(nèi)部用到addEventListener/attachEvent。能把多個(gè)函數(shù)加到一個(gè)觸發(fā)事件(window.onload)。bind是覆蓋。
6、關(guān)于事件監(jiān)聽最佳實(shí)踐
很顯然prototype.js提供的事件注冊(cè)方法不是很完善。那看看dojo的時(shí)間注冊(cè)吧(中文版),更加復(fù)雜,估計(jì)很多人像我一樣,對(duì)于dojo暫時(shí)持觀望態(tài)度。
如果你看過的前篇關(guān)于閉包的介紹,可能見過以下代碼。
看以下代碼前我想表述一個(gè)觀點(diǎn),任何網(wǎng)頁中元素,瀏覽器都會(huì)為你創(chuàng)建一個(gè)對(duì)象(見)。(我覺得)這些對(duì)象與你建立javascript對(duì)象區(qū)別是它們有事件監(jiān)聽,會(huì)響應(yīng)鼠標(biāo)鍵盤的事件。如果你用了以下代碼,那么把事件監(jiān)聽代碼很好的轉(zhuǎn)化到你的javascript代碼中。
function associateObjWithEvent(obj, methodName){
return (function(e){
e = e||window.event;
return obj[methodName](e, this);
});
}
function DhtmlObject(elementId){
var el = getElementWithId(elementId);
if(el){
el.onclick = associateObjWithEvent(this, "doOnClick");
el.onmouseover = associateObjWithEvent(this, "doMouseOver");
el.onmouseout = associateObjWithEvent(this, "doMouseOut");
}
}
DhtmlObject.prototype.doOnClick = function(event, element){
... // doOnClick method body.
}
DhtmlObject.prototype.doMouseOver = function(event, element){
... // doMouseOver method body.
}
DhtmlObject.prototype.doMouseOut = function(event, element){
... // doMouseOut method body.
}
有時(shí)間我想用以上思想實(shí)現(xiàn)一個(gè)網(wǎng)頁浮動(dòng)框拖拉的代碼(其實(shí)已經(jīng)有很多了),待續(xù)........
prototype.js中用了大量的apply和call函數(shù),不注意會(huì)造成理解偏差。
官方解釋:應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
apply與call的區(qū)別是第二個(gè)參數(shù)不同。apply是 數(shù)組或者arguments 對(duì)象。而call是逗號(hào)隔開的任何類型。
apply,call方法最讓人混淆的地方也是apply,call的特色。但最好不要濫用。
能改變調(diào)用函數(shù)的對(duì)象。如下例,函數(shù)中用到this關(guān)鍵字,這時(shí)候this代表的是apply,call函數(shù)的第一個(gè)參數(shù)。
<script src="prototype1.3.1.js"></script>
<input type="text" id="myText" value="input text">
<script>
function Obj(){
this.value="對(duì)象!";
}
var value="global 變量";
function Fun1(){
alert(this.value);
}
window.Fun1();
Fun1.apply(window);
Fun1.apply($('myText'));
Fun1.apply(new Obj());
</script>
2、關(guān)于閉包
prototype.js在Class.create,bind等中用到j(luò)avascript的閉包特色。但整體上prototype.js對(duì)于強(qiáng)大的閉包特性用的不多。大家可以參閱我翻譯的篇文章了解閉包。
3、讓我比較反感的兩個(gè)方法
(1)
var Class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
很討厭用別的語言的風(fēng)格來寫javascript。用這個(gè)方法構(gòu)造自定義類 并沒有覺得有多方便,減少代碼行數(shù),只會(huì)讓人難理解,多定義一個(gè)initialize方法。
其實(shí)討厭這條有些牽強(qiáng),不過修改Object的原型對(duì)象就有點(diǎn)過分了。
(2)Object.prototype.extend
先不過你取個(gè)extend的名字會(huì)讓熟悉java的人引起的歧義。修改Object的prototype就說不過去了。不知道作者是怎么考慮的。當(dāng)你for in循環(huán)對(duì)象是,麻煩就來了??赡苡腥藭?huì)問你for in干嗎。 我一個(gè)項(xiàng)目中既用了DWR,也用了prototype.js,dwr返回的javascript對(duì)象都多了個(gè)exetend屬性,還得特殊處理。
以前我比較過dojo和prototype.js中繼承的實(shí)現(xiàn),現(xiàn)在我明白個(gè)道理。對(duì)于javascript這種沒有靜態(tài)類型檢查,語法寬松的語言來講,如果你選擇了某個(gè)js類庫,那你也必須適應(yīng)作者寫javascript的風(fēng)格。prototype.js的作者對(duì)extend的使用爐火純青,如果我們不當(dāng)它只是個(gè)屬性拷貝的函數(shù)的話,多讀讀prototype.js的代碼是好的。
4、關(guān)于函數(shù)的綁定
類庫提供了Function.prototype.bind Function.prototype.bindAsEventListener兩個(gè)方法。首先我們從概念上解釋一個(gè)這兩個(gè)方法。
任何一個(gè)函數(shù)都可以調(diào)用這兩個(gè)方法;參數(shù)的是javascript對(duì)象或網(wǎng)頁上元素對(duì)象;返回類型是個(gè)函數(shù)對(duì)象。
本來我就是個(gè)函數(shù),返回還是函數(shù),到這兩個(gè)函數(shù)有什么不同呢??磳?shí)現(xiàn)代碼,關(guān)鍵還是apply\call函數(shù)的代碼。其實(shí)這里只是轉(zhuǎn)化了一下方法調(diào)用的對(duì)象。
<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="asf" value=1> Test
<script>
var CheckboxWatcher = Class.create();
CheckboxWatcher.prototype = {
initialize: function(chkBox, message) {
this.chkBox = $(chkBox);
this.message = message;
this.chkBox.onclick = this.showMessage.bindAsEventListener(this);
},
showMessage: function(evt) {
alert(this.message + ' (' + evt.type + ')');
}
};
new CheckboxWatcher('myChk','message!!!!');
//$('myChk').onclick=function(){};
</script>
這是 https://compdoc2cn.dev.java.net/ 上舉的例子,個(gè)人感覺沒什么意思,反而讓我對(duì)bind,bindAsEventListener有些反感。(javascript就是這樣,明明大家都知道的語法,但寫出來的代碼差別確很大)
看下面代碼:
<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="chk" value=1> Test
<script>
function Class(){
this.name="class";
}
Class.prototype.getName=function(){
alert(this.name);
}
var obj=new Class();
//$('myChk').onclick=obj.getName;
$('myChk').onclick=obj.getName.bind(obj);
//$('myChk').onclick=obj.getName.bind($('myChk'));
</script>
從上面代碼可以看出bind/bindAsEventListener只是包裝了一下apply/call方法,改變方法的調(diào)用對(duì)象。如例子,你可以把obj.getName方法轉(zhuǎn)化成任何對(duì)象調(diào)用,并且把方法讓表單元素觸發(fā)。(bind和bindAsEventListener之間只是返回函數(shù)的參數(shù)不同)
這兩個(gè)方法也可以用在對(duì)象之間的方法重用,實(shí)現(xiàn)類似繼承方法的概念??匆韵麓a,其實(shí)是比較無聊的。
<script src="prototype1.3.1.js"></script>
<script>
function Class1(name){
this.name=name;
}
Class1.prototype.getName=function(){
alert(this.name);
}
function Class2(name){
this.name=name;
this.getName=Class1.prototype.getName.bind(this);
}
var obj1=new Class2("yql");
obj1.getName();
var obj2=new Object();
obj2.name="zkj";
obj2.fun=Class1.prototype.getName.bind(obj2);
obj2.fun();
</script>
我從來沒讀過prototype.js的擴(kuò)展項(xiàng)目代碼,也不知道bind..的最佳實(shí)踐,一起挖掘吧。但你絕對(duì)不要把bind/bindAsEventListener從綁定的詞義上來理解,可能會(huì)讓你更加迷惑。從apply/call理解本質(zhì)。應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
5、關(guān)于事件的注冊(cè)
<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="chk" value=1> Test
<script>
Event.observe(myChk, 'click', showMessage, false);
//$('myChk').onclick=showMessage;
//$('myChk').onclick=showMessage.bind();
$('myChk').onclick=showMessage.bind($('myChk'));
function showMessage() {
alert(this.value);
}
</script>
執(zhí)行上面代碼,你就能明白Event.observe與bind/bindAsEventListener之間的區(qū)別:
(1) 顯然Event.observe有限制,只能處理簡(jiǎn)單的函數(shù),并函數(shù)中不能有this之類的東西。
(2)Event.observe內(nèi)部用到addEventListener/attachEvent。能把多個(gè)函數(shù)加到一個(gè)觸發(fā)事件(window.onload)。bind是覆蓋。
6、關(guān)于事件監(jiān)聽最佳實(shí)踐
很顯然prototype.js提供的事件注冊(cè)方法不是很完善。那看看dojo的時(shí)間注冊(cè)吧(中文版),更加復(fù)雜,估計(jì)很多人像我一樣,對(duì)于dojo暫時(shí)持觀望態(tài)度。
如果你看過的前篇關(guān)于閉包的介紹,可能見過以下代碼。
看以下代碼前我想表述一個(gè)觀點(diǎn),任何網(wǎng)頁中元素,瀏覽器都會(huì)為你創(chuàng)建一個(gè)對(duì)象(見)。(我覺得)這些對(duì)象與你建立javascript對(duì)象區(qū)別是它們有事件監(jiān)聽,會(huì)響應(yīng)鼠標(biāo)鍵盤的事件。如果你用了以下代碼,那么把事件監(jiān)聽代碼很好的轉(zhuǎn)化到你的javascript代碼中。
function associateObjWithEvent(obj, methodName){
return (function(e){
e = e||window.event;
return obj[methodName](e, this);
});
}
function DhtmlObject(elementId){
var el = getElementWithId(elementId);
if(el){
el.onclick = associateObjWithEvent(this, "doOnClick");
el.onmouseover = associateObjWithEvent(this, "doMouseOver");
el.onmouseout = associateObjWithEvent(this, "doMouseOut");
}
}
DhtmlObject.prototype.doOnClick = function(event, element){
... // doOnClick method body.
}
DhtmlObject.prototype.doMouseOver = function(event, element){
... // doMouseOver method body.
}
DhtmlObject.prototype.doMouseOut = function(event, element){
... // doMouseOut method body.
}
有時(shí)間我想用以上思想實(shí)現(xiàn)一個(gè)網(wǎng)頁浮動(dòng)框拖拉的代碼(其實(shí)已經(jīng)有很多了),待續(xù)........
您可能感興趣的文章:
- Javascript基于對(duì)象三大特性(封裝性、繼承性、多態(tài)性)
- javascript的函數(shù)、創(chuàng)建對(duì)象、封裝、屬性和方法、繼承
- JavaScript面向?qū)ο笾甈rototypes和繼承
- javascript 面向?qū)ο?實(shí)現(xiàn)namespace,class,繼承,重載
- javascript 面向?qū)ο笕吕砭氈屠^承
- JS 面向?qū)ο笾^承---多種組合繼承詳解
- javascript 面向?qū)ο缶幊袒A(chǔ):繼承
- javascript 面向?qū)ο笕吕砭氈^承與多態(tài)
- js對(duì)象繼承之原型鏈繼承實(shí)例
- JavaScript面向?qū)ο蟪绦蛟O(shè)計(jì)中對(duì)象的定義和繼承詳解
相關(guān)文章
JavaScript中工廠函數(shù)與構(gòu)造函數(shù)示例詳解
這篇文章主要給大家介紹了關(guān)于JavaScript中工廠函數(shù)與構(gòu)造函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用JavaScript具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05javascript代碼調(diào)試之console.log 用法圖文詳解
對(duì)于開始學(xué)js的朋友可能不知道為什么用console.log,頁面中也看不到信息,對(duì)于這個(gè)console.log腳本之家小編特整理與介紹一下,方便需要的朋友2016-09-09es7學(xué)習(xí)教程之Decorators(修飾器)詳解
這篇文章主要給大家介紹了關(guān)于es7中Decorators(修飾器)的相關(guān)資料,文中通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2017-07-07關(guān)于取不到由location.href提交而來的上級(jí)頁面地址的解決辦法
驗(yàn)證上級(jí)頁面來源取不到由location.href提交而來的頁面地址,搜索了一大堆沒有合適的解決辦法,突然想到通過模擬JS點(diǎn)擊鏈接的方法2009-07-07bootstrap table方法之expandRow-collapseRow展開或關(guān)閉當(dāng)前行數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了bootstrap table方法之expandRow-collapseRow展開或關(guān)閉當(dāng)前行數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09