淺析Javascript原型繼承 推薦第2/2頁
更新時間:2009年07月27日 17:34:56 作者:
JS沒有提供所謂的類繼承,據(jù)說在2.0中要加入這種繼承方式,但是要所有瀏覽器都實現(xiàn)2.0的特性那肯定又得N多年。
復制代碼 代碼如下:
//方法一
//Prototype框架采用了此種方法
Hoozit.prototype = new Gizmo(2);
Hoozit.prototype.constructor = Hoozit;
//方法二
function Hoozit(id) {
this.id = id;
this.constructor=Hoozit;
}
//具體兩種方法有什么區(qū)別,請參考《JAVASCRIPT語言精髓與編程實踐》158~159頁。
有興趣的可以結合上面的圖,想想這兩種方法的Hoozit.prototype.constructor應該放在圖的什么位置?想不明白的可以和我在交流。
下面看一下《JAVASCRIPT語言精髓和編程實踐》書上的一張圖(156~157頁):

個人認為這張圖下面的那個constructor屬性的指向是不是有問題?書上面表達的意思肯定沒有問題,但這張圖畫的很困惑。和我上面的解釋不太一樣?先不說這個了,大家自己研究研究吧。
下面我們再來說一下我給出的原型繼承圖中的右邊灰色的箭頭部分。從這部分能夠看出繼承的關系。所有未經(jīng)過變動的函數(shù)(構造器)的原型,他們都會繼承自Object對象。
alert(Gizmo.prototype instanceof Object.prototype.constructor); //true
這樣原型的繼承關系就連接起來了。其實說白了,就是一個函數(shù)的prototype鏈向另一個函數(shù)實例,然后不斷的這樣進行下去,最上面的函數(shù)鏈接Object至對象實例,OK,所有函數(shù)就都連接起來了。
PS:
“還有要注意的是只有在new Gizmo()之后,才能添加test等其它方法,這個順序不能倒過來!“ 這個問題是不是清楚了呢?
下面看幾個例子,說明幾個問題:
復制代碼 代碼如下:
function Gizmo(id) {
this.id = id;
this.ask=function(){
alert("gizmo--ask:"+this.id);
}
function privateMethod(){
return "gizmo--privateMethod";
}
privateMethod2=function(){
return "gizmo--privateMethod2";
}
}
Gizmo.prototype.toString = function () {
return "gizmo--toString:" + this.id;
};
Gizmo.prototype.id="gizmo3";
function Hoozit(id) {
this.id = id;
}
Hoozit.prototype = new Gizmo("gizmo1");
var g=new Gizmo("gizmo2");
var h=new Hoozit("hoozit");
問題一:
復制代碼 代碼如下:
h.ask=function(){
alert("h.ask");
}
h.ask();
delete h.ask; //"h.ask"
h.ask(); //"gizmo--ask:hoozit"
delete h.id
h.ask(); //"gizmo--ask:gizmo1"
delete Hoozit.prototype.id
h.ask(); //"gizmo--ask:gizmo3"
/*
這里要說明的問題是:對象是如何找到屬性和方法的?
第一步:先在實例對象上找ask方法,找到了,調(diào)用。第一個ask說明了這個問題
第二步:如果實例上沒有ask方法,在自己的原型對象里面找ask方法,找到調(diào)用(沒有給出這樣的示例)
第三步:如果自己的原型中沒有,回溯原型鏈,在父原型鏈中找ask方法,找到調(diào)用,第二個ask說明了這個問題,這里會一直遞歸找到Object對象,如果還沒找到,那就會報錯了
*/
/*
再來看屬性查找:
首先找實例對象上的屬性,所以第二個ask輸出"gizmo--ask:hoozit",即id="hoozit"
然后找自己原型中的屬性,刪除掉h.id之后,找到原型上的屬性,所以id="gizmo1"
接著遞歸原型鏈,找父對象原型中的屬性,一直找到Object對象,所以刪除掉Hoozit.prototype.id之后,id="gizmo3"
*/
問題二:
復制代碼 代碼如下:
Gizmo.prototype.question = function () {
alert("gizmo--question:" + this.id);
};
h.question();
/*
方法可以隨時添加,添加完之后就可以調(diào)用
*/
問題三:
復制代碼 代碼如下:
Hoozit.prototype.toString = function () {
return "hoozit--toString:" + this.id;
};
alert(h);
delete Hoozit.prototype.toString;
alert(h);
/*
這個問題和問題一有些重復,這里更清楚的看出,刪除掉自己原型上的方法之后,就會找父原型中的方法
*/
問題四:
復制代碼 代碼如下:
h.question.call(g);
alert(h.toString.call(g));
h.question.apply(g);
alert(h.toString.apply(g));
/*
可以利用apply和call方法把要調(diào)用的方法綁定到其它實例。通過結果可以看出上面那種方法調(diào)用輸出的id是g對象的,而不是h對象的
*/
問題五:
復制代碼 代碼如下:
alert(h.privateMethod());
alert(g.privateMethod2());
/*
上面的任意一個調(diào)用都會報錯,也就是說通過顯示命名函數(shù)或者匿名函數(shù)但是不加this的聲明方式定義在函數(shù)之內(nèi)的函數(shù),是不能被外界訪問的。這里一定注意第二種private方法聲明,省略了this外面就訪問不到了!
*/
/*
命名函數(shù):(函數(shù)名字為func1)
function func1(){}
匿名函數(shù):(注意這里,func1不是函數(shù)的名字,僅僅是個別名而已,可以通過func()來調(diào)用這個匿名函數(shù))
func1=function(){}
*/
pdf文件下載http://xiazai.jb51.net/200907/books/javascript_yuanxing.rar
相關文章
javascript最常用與實用的創(chuàng)建類的代碼
組合構造函數(shù)模式和原型模式2010-08-08詳解new function(){}和function(){}() 區(qū)別分析
只要 new 表達式之后的 constructor 返回(return)一個引用對象(數(shù)組,對象,函數(shù)等),都將覆蓋new創(chuàng)建的匿名對象,如果返回(return)一個原始類型(無 return 時其實為 return 原始類型 undefined),那么就返回 new 創(chuàng)建的匿名對象。2008-03-03JavaScript的單例模式 (singleton in Javascript)
JavaScript的單例模式 (singleton in Javascript)2010-06-06JavaScript 創(chuàng)建對象和構造類實現(xiàn)代碼
JavaScript學習筆記:創(chuàng)建對象和構造類.2009-07-07