Javascript 原型和繼承(Prototypes and Inheritance)
更新時(shí)間:2009年04月01日 22:33:56 作者:
前面我們看到了如何使用 constructor 來初始化對象。如果這樣做,那么每一個(gè)創(chuàng)建的新對象都會(huì)對那些相同的屬性,方法建立一個(gè)獨(dú)立的副本。而實(shí)際上有更加有效的方法來指定方法,常量,以及其他一些可被所有該類的對象共享的屬性。
JavaScript 對象從一個(gè)原形對象(prototype object) 繼承屬性。所有對象都有原型;原型的所有屬性看上去就像使用它作為原型的那些對象的屬性一樣。簡單的說就是:所有對象都從他的原型繼承屬性。
(each object inherits properties from its prototype).
對象的 prototype 通過它的 constructor function 來定義。JavaScript 里所有的 function 都有一個(gè) prototype 屬性。這個(gè)屬性開始是空的,接下來你給他添加的任何屬性都會(huì)被 constructor 創(chuàng)建的對象所擁有。
prototype 對象和 constructor 相關(guān)聯(lián)。這意味著 prototype 可以作為放置方法以及其他常量的理想場所。原型中的屬性不會(huì)被復(fù)制到新創(chuàng)建的對象中去,他們的屬性看上去就像對象的屬性一樣。這意味著,使用原型能夠大幅度的減少多個(gè)同類對象占用的內(nèi)存。
每一個(gè) class 都只有一個(gè) prototype object, 附帶一套屬性。但我們在運(yùn)行時(shí)可能會(huì)創(chuàng)建多個(gè)類的實(shí)例。那么如果發(fā)生對原型的屬性的讀寫會(huì)發(fā)生什么情況?
當(dāng)你讀一個(gè)屬性的時(shí)候,JavaScript 首先嘗試去查找對象本身是否有這個(gè)屬性,如果沒有,接著去查找原型里面是否有。有的話就返回結(jié)果。
而當(dāng)你寫原型的屬性的時(shí)候,因?yàn)槎鄠€(gè)對象共享原型,顯然是不能直接在原型上進(jìn)行寫操作的。這個(gè)時(shí)候?qū)嶋H上 JavaScript 會(huì)在對象上創(chuàng)建一個(gè)同名的屬性,然后把值寫到里面。當(dāng)你下次讀這個(gè)屬性的時(shí)候,JavaScript 一下子就在對象的屬性里查找到了,那么就不需要去原型里查找了。這個(gè)時(shí)候,我們說“對象的屬性掩蓋或隱藏了原型的屬性”。(shadows or hides) 。
從上面討論看出,其實(shí)我們在設(shè)計(jì)類的時(shí)候,只要掌握一個(gè)原則:在原型里僅定義一些方法(方法一般是不會(huì)變的),常數(shù),常量等。做到這一點(diǎn)就不容易混淆了。
例子:
// Define a constructor method for our class.
// Use it to initialize properties that will be different for
// each individual Circle object.
functionCircle(x, y, r)
{
this.x = x; // The X-coordinate of the center of the circle
this.y = y; // The Y-coordinate of the center of the circle
this.r = r; // The radius of the circle
}
// Create and discard an initial Circle object.
// This forces the prototype object to be created in JavaScript 1.1.
new Circle(0,0,0);
// Define a constant: a property that will be shared by
// all circle objects. Actually, we could just use Math.PI,
// but we do it this way for the sake of instruction.
Circle.prototype.pi =
3.14159;
// Define a method to compute the circumference of the circle.
// First declare a function, then assign it to a prototype property.
// Note the use of the constant defined above.
function Circle_circumference( ) { return
2
*
this.pi *
this.r; }
Circle.prototype.circumference =Circle_circumference;
// Define another method. This time we use a function literal to define
// the function and assign it to a prototype property all in one step.
Circle.prototype.area =
function( ) { return
this.pi *
this.r *
this.r; }
// The Circle class is defined.
// Now we can create an instance and invoke its methods.
var c =
new Circle(0.0, 0.0, 1.0);
var a =c.area( );
var p = c.circumference( );
內(nèi)置的類的 prototype.
不光是用戶自定義的類可以有 prototype. 系統(tǒng)內(nèi)置的類比如 String, Date 也都有的。而且你可以向他們添加新的方法,屬性等。
下面這段代碼就對所有的 String 對象添加了一個(gè)有用的函數(shù):
// Returns true if the last character is c
String.prototype.endsWith =
function(c) {
return (c ==
this.charAt(this.length-1))
}
然后我們就可以類似這樣的來調(diào)用了:
var message =
"hello world";
message.endsWith('h') // Returns false
message.endsWith('d') // Returns true
(each object inherits properties from its prototype).
對象的 prototype 通過它的 constructor function 來定義。JavaScript 里所有的 function 都有一個(gè) prototype 屬性。這個(gè)屬性開始是空的,接下來你給他添加的任何屬性都會(huì)被 constructor 創(chuàng)建的對象所擁有。
prototype 對象和 constructor 相關(guān)聯(lián)。這意味著 prototype 可以作為放置方法以及其他常量的理想場所。原型中的屬性不會(huì)被復(fù)制到新創(chuàng)建的對象中去,他們的屬性看上去就像對象的屬性一樣。這意味著,使用原型能夠大幅度的減少多個(gè)同類對象占用的內(nèi)存。
每一個(gè) class 都只有一個(gè) prototype object, 附帶一套屬性。但我們在運(yùn)行時(shí)可能會(huì)創(chuàng)建多個(gè)類的實(shí)例。那么如果發(fā)生對原型的屬性的讀寫會(huì)發(fā)生什么情況?
當(dāng)你讀一個(gè)屬性的時(shí)候,JavaScript 首先嘗試去查找對象本身是否有這個(gè)屬性,如果沒有,接著去查找原型里面是否有。有的話就返回結(jié)果。
而當(dāng)你寫原型的屬性的時(shí)候,因?yàn)槎鄠€(gè)對象共享原型,顯然是不能直接在原型上進(jìn)行寫操作的。這個(gè)時(shí)候?qū)嶋H上 JavaScript 會(huì)在對象上創(chuàng)建一個(gè)同名的屬性,然后把值寫到里面。當(dāng)你下次讀這個(gè)屬性的時(shí)候,JavaScript 一下子就在對象的屬性里查找到了,那么就不需要去原型里查找了。這個(gè)時(shí)候,我們說“對象的屬性掩蓋或隱藏了原型的屬性”。(shadows or hides) 。
從上面討論看出,其實(shí)我們在設(shè)計(jì)類的時(shí)候,只要掌握一個(gè)原則:在原型里僅定義一些方法(方法一般是不會(huì)變的),常數(shù),常量等。做到這一點(diǎn)就不容易混淆了。
例子:
// Define a constructor method for our class.
// Use it to initialize properties that will be different for
// each individual Circle object.
functionCircle(x, y, r)
{
this.x = x; // The X-coordinate of the center of the circle
this.y = y; // The Y-coordinate of the center of the circle
this.r = r; // The radius of the circle
}
// Create and discard an initial Circle object.
// This forces the prototype object to be created in JavaScript 1.1.
new Circle(0,0,0);
// Define a constant: a property that will be shared by
// all circle objects. Actually, we could just use Math.PI,
// but we do it this way for the sake of instruction.
Circle.prototype.pi = 3.14159;
// Define a method to compute the circumference of the circle.
// First declare a function, then assign it to a prototype property.
// Note the use of the constant defined above.
function Circle_circumference( ) { return 2
*
this.pi *
this.r; }
Circle.prototype.circumference =Circle_circumference;
// Define another method. This time we use a function literal to define
// the function and assign it to a prototype property all in one step.
Circle.prototype.area = function( ) { return
this.pi *
this.r *
this.r; }
// The Circle class is defined.
// Now we can create an instance and invoke its methods.
var c = new Circle(0.0, 0.0, 1.0);
var a =c.area( );
var p = c.circumference( ); 內(nèi)置的類的 prototype.
不光是用戶自定義的類可以有 prototype. 系統(tǒng)內(nèi)置的類比如 String, Date 也都有的。而且你可以向他們添加新的方法,屬性等。
下面這段代碼就對所有的 String 對象添加了一個(gè)有用的函數(shù):
// Returns true if the last character is c
String.prototype.endsWith = function(c) {
return (c == this.charAt(this.length-1))
} 然后我們就可以類似這樣的來調(diào)用了:
var message = "hello world";
message.endsWith('h') // Returns false
message.endsWith('d') // Returns true
您可能感興趣的文章:
- Javascript中 關(guān)于prototype屬性實(shí)現(xiàn)繼承的原理圖
- JavaScript類和繼承 prototype屬性
- js中繼承的幾種用法總結(jié)(apply,call,prototype)
- 深入了解javascript中的prototype與繼承
- javascript prototype的深度探索不是原型繼承那么簡單
- JavaScript面向?qū)ο笾甈rototypes和繼承
- JavaScript不使用prototype和new實(shí)現(xiàn)繼承機(jī)制
- JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài)示例
- javascript基于prototype實(shí)現(xiàn)類似OOP繼承的方法
- Javascript中的prototype與繼承
- JS偽繼承prototype實(shí)現(xiàn)方法示例
- JavaScript使用prototype屬性實(shí)現(xiàn)繼承操作示例
相關(guān)文章
baidu博客的編輯友情鏈接的新的層窗口!經(jīng)典~支持【FF】
baidu博客的編輯友情鏈接的新的層窗口!經(jīng)典~支持【FF】...2007-02-02
Bootstrap進(jìn)度條學(xué)習(xí)使用
這篇文章主要為大家詳細(xì)介紹了Bootstrap進(jìn)度條的學(xué)習(xí)使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
js獲得當(dāng)前時(shí)區(qū)夏令時(shí)發(fā)生和終止的時(shí)間代碼
這篇文章主要介紹了js獲得當(dāng)前時(shí)區(qū)夏令時(shí)發(fā)生和終止的時(shí)間代碼,需要的朋友可以參考下2014-02-02
layer.alert自定義關(guān)閉回調(diào)事件的方法
今天小編就為大家分享一篇layer.alert自定義關(guān)閉回調(diào)事件的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-09-09
echarts自定義tooltip中的內(nèi)容代碼示例
在ECharts中,通過formatter函數(shù)自定義圖例樣式,可以實(shí)現(xiàn)更靈活的圖表展示,滿足特定的視覺需求,這篇文章主要介紹了echarts自定義tooltip中內(nèi)容的相關(guān)資料,需要的朋友可以參考下2024-10-10
javascript實(shí)現(xiàn)秒表計(jì)時(shí)器的制作方法
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)秒表計(jì)時(shí)器的制作方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
typescript+react實(shí)現(xiàn)移動(dòng)端和PC端簡單拖拽效果
這篇文章主要為大家詳細(xì)介紹了typescript+react實(shí)現(xiàn)移動(dòng)端和PC端簡單拖拽效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09

