日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

在Javascript中使用面向对象的编程

發(fā)布時間:2023/11/27 生活经验 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在Javascript中使用面向对象的编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
by Mike Koss
March 26th, 2003

這是一篇,我個人認為最好的,Javascript面向?qū)ο缶幊痰奈恼隆7g不好的地方,還望大家指正,謝謝。
如果您需要,可以訪問下面的地址取得原文: http://mckoss.com/jscript/object.htm
在我的blog里,將會陸續(xù)推出這個理論的實踐、源碼。

介紹

大部分的Javascript的編寫者,都只是把它做為簡單的腳本引擎,來創(chuàng)建動態(tài)的Web頁面。同時Web設(shè)計人員開始使用在IE瀏覽器中定義的對象模型,來處理Web頁面的內(nèi)容。但是大多數(shù)的開發(fā)者并沒有認識到Javascript在其自身就具有強大的面向?qū)ο蟮墓δ堋.?dāng)不使用強類型的時候(變量不必先聲明后使用),這種解析性的語言,可以巧妙的達成面向?qū)ο?#xff08;object-oriented)的功能,包括:

  • 封裝?(Encapsulation)
  • 多臺?(Polymorphism )
  • 繼承?(Inheritance)

雖然,通過一系列的范例(對于好奇的讀者,這些范例片斷代碼是很生動的),我將會闡述對象在Javascript中,對象是如何被使用,并且如何實現(xiàn)面向?qū)ο蟮摹?/p>

簡單對象(Simple Objects)

在Javascript中,最簡單的可構(gòu)建的對象,就是機制內(nèi)建的Object對象。在Javascript中,對象是指定名稱的屬性(property)的集合。做為解析性語言,Javascript允許給一個對象創(chuàng)建任意個屬性,在任何時間(不像C++,它的屬性是可以在任何時間添加給對象。它們并不需要事先在對象的聲明(definition)或者構(gòu)造(constructor)中,進行定義)。

所以,舉例來說,我們可以創(chuàng)建一個對象,然后添加一系列的屬性給它,就像這樣:

obj = new Object;<br><br>obj.x = 1;<br><br>obj.y = 2;

這里,Javascript對象,可以用圖形表示成這樣的結(jié)構(gòu):

obj
x1
y2
prototype properties
constructor
function?Object

另外需要注意的是,我們創(chuàng)建的x和y屬性, 我們的對象默認有一個屬性constructor t他指向一個Javascript內(nèi)部對象函數(shù)(funciton)。 (譯者注:prototype,原型在后文會有進一步的說明)

對象的構(gòu)造函數(shù)(Object Constructors)

對于要定義的對象類型,Javascript允許我們自己給對象類型定義構(gòu)造函數(shù):

function Foo()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x = 1;<br><br>&nbsp;&nbsp;&nbsp; this.y = 2;<br><br>}<br><br> <br><br>obj1 = new Foo;<br><br>
obj1
x1
y2
prototype properties
constructorfunction?Foo

這里要說明的是,我們可以創(chuàng)建任意多個Foo類型的對象實例,它們也都將分別初始化自己的x和y屬性為1和2。

簡單的方法的的實現(xiàn)(A Simple Method Implementation)

為了封裝對象的行為功能,向調(diào)用者隱藏執(zhí)行過程,我們需要給對象創(chuàng)建方法(method)。Javascript允許你將任意一個函數(shù)(function)分配給對象的一個屬性。當(dāng)我們使用 obj.Function 的語法調(diào)用函數(shù)的時候,將把函數(shù)原來定義this 的指向,當(dāng)前這個對象(就像它在構(gòu)造函數(shù)中的那樣)。

function Foo()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x = 1;<br><br>&nbsp;&nbsp;&nbsp; this.y = 2;<br><br>&nbsp;&nbsp;&nbsp; this.Bar = MyMethod;<br><br>}<br><br> <br><br>function MyMethod(z)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x += z;<br><br>}<br><br> <br><br>obj2 = new Foo;<br><br>
obj2
x1
y2
Barfunction?MyMethod
prototype properties
constructorfunction?Foo

現(xiàn)在,我們簡單的調(diào)用一下,做為對象的方法的Bar函數(shù):

obj2.Bar(3);<br><br>
obj2
x4
y2
Barfunction?MyMethod
prototype properties
constructorfunction?Foo

所以,你可以方便的給對象定義構(gòu)造函數(shù)和方法,使其對調(diào)用者而言,隱藏它的實現(xiàn)過程。同樣的,因為,Javascript不是強類型的,所以,我們可以通過定義有相同名字的方法的對象,來簡單的實現(xiàn)多臺性(polymorphism)。

function Foo()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x = 1;<br><br>&nbsp;&nbsp;&nbsp; this.DoIt = FooMethod;<br><br>}<br><br> <br><br>function FooMethod()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x++;<br><br>}<br><br> <br><br>function Bar()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.z = 'Hello';<br><br>&nbsp;&nbsp;&nbsp; this.DoIt = BarMethod;<br><br>}<br><br> <br><br>function BarMethod()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.z += this.z;<br><br>}<br><br> <br><br>obj1 = new Foo;<br><br>obj2 = new Bar;<br><br>
obj1
x1
DoItfunction?FooMethod
prototype properties
constructorfunction?Foo
obj2
zHello
DoItfunction?BarMethod
prototype properties
constructorfunction?Bar
function Poly(obj)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; obj.DoIt();<br><br>}<br><br> <br><br>Poly(obj1);<br><br>Poly(obj2);<br><br>
obj1
x2
DoItfunction?FooMethod
prototype properties
constructorfunction?Foo
obj2
zHelloHello
DoItfunction?BarMethod
prototype properties
constructorfunction?Bar

使用原型實現(xiàn)方法(Using Prototypes to Implement Methods)

試想一下,這使很笨的辦法,每次我們都要創(chuàng)建名稱沒有使用意義的方法函數(shù),然后在構(gòu)造函數(shù)里,把它們分配給每個方法屬性。其實,我發(fā)現(xiàn)使用Javascript的原型(prototype)機制,是更為直接的方法。?

每個對象,可以參照一個原型對象,原型對象包含有自己的屬性。它就好比是一個對象定義的備份。當(dāng)代碼,引用一個屬性的時候,它并不存在于對象本身里,那么Javascript將會自動的在原型的定義中查找這個屬性。而且,事實上,一個對象的原型對象又可以參照另外一個原型對象,就這樣以鏈?zhǔn)阶罱K關(guān)聯(lián)到基類對象的構(gòu)造函數(shù)。(譯者注:對于DOM對象等系統(tǒng)的對象,原型對象可以修改,但是不可以賦值改變的,只有自定義對象可以。)這是template模型(譯者注:模板方法,《設(shè)計模式》中行為模式的一種),它可以簡化我們對方法的定義,同時也可以產(chǎn)生強大的繼承機制。

在Javascript中,原型對象是被分配給構(gòu)造函數(shù)的。所以,為了修改對象的原型,必須首先修改構(gòu)造函數(shù)的原型對象的成員。然后,當(dāng)對象從構(gòu)造函數(shù)被構(gòu)造的時候,對象將會引用到構(gòu)造函數(shù)的原型。?

function Foo()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x = 1;<br><br>}<br><br> <br><br>Foo.prototype.y = 2;<br><br>obj = new Foo;<br><br>document.write('obj.y = ' + obj.y);<br><br>obj.y = 2
obj
x1
prototype properties
constructorfunction?Foo
prototype
y2
y2

即使我們并沒有直接的把y屬性分配給obj,obj對象仍然有一個y屬性。當(dāng)我們引用obj.y的時候,Javascript實際返回obj.constructor.prototype.y的引用。我們可以肯定的是,原型的值的改變,也將會反映到對象中。?

Foo.prototype.y = 3;<br><br>document.write('obj.y = ' + obj.y);<br><br>obj.y = 3
obj
x1
prototype properties
constructorfunction?Foo
prototype
y3
y3
我們也可以發(fā)現(xiàn),一旦我們初始化一個屬性的“私有”( private )的值,存放在原型中的值并不會收到影響:
obj.y = 4;<br><br>Foo.prototype.y = 3;<br><br>
obj
x1
y4
prototype properties
constructorfunction?Foo
prototype
y3

原型方法的命名(Prototype Method Naming)

我發(fā)現(xiàn)了可以直接定義類的原型的方法的語句,而不需要單獨的函數(shù)的名稱:

function Foo()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x = 1;<br><br>}<br><br> <br><br>function Foo.prototype.DoIt()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.x++;<br><br>}<br><br>obj = new Foo;<br><br>obj.DoIt();
obj
x2
prototype properties
constructorfunction?Foo
prototype
DoItfunction?Foo.prototype.DoIt
DoItfunction?Foo.prototype.DoIt

基于原型的子類繼承(Prototype-based Subclassing )

一旦可以建立原型對象鏈,我們就可以使用它做為對象的子類的類型。這個方法要注意的是,我們創(chuàng)建了一個基類對象的實例,并把它做為我們的類的構(gòu)造函數(shù)的原型對象。這么做,我們所創(chuàng)建的所有的對象,將繼承基類對象的所有成員和(方法)。但是要注意,基類的構(gòu)造函數(shù)只會被調(diào)用一次(譯者注:從基類到子類的構(gòu)造函數(shù)都是唯一的,即基類的構(gòu)造函數(shù))。這不像C++,基類的構(gòu)造函數(shù),對于每個繼承的子類,都可以分別的調(diào)用。在后面,我將展示,當(dāng)獨立的構(gòu)造函數(shù)被需要的時候,另外一種可選的方式來創(chuàng)建繼承類。
function TextObject(st)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.st = st;<br><br>&nbsp;&nbsp;&nbsp; this.fVisible = true;<br><br>}<br><br> <br><br>function TextObject.prototype.Write()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; document.write('<br><br>' + this.st);<br><br>}<br><br> <br><br>function ItalicTextObject(st)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.st = st;<br><br>}<br><br> <br><br>ItalicTextObject.prototype = new TextObject('x');<br><br> <br><br>ItalicTextObject.prototype.Write = ITOWrite;<br><br>function ITOWrite()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; document.write('<br><br><em>' + this.st + '</em>');<br><br>}<br><br> <br><br>obj1 = new TextObject('Hello, mom');<br><br>obj2 = new ItalicTextObject('Hello, world');<br><br>obj1.Write();<br><br>obj2.Write();<br><br>
Hello, mom
Hello, world
obj1
stHello,?mom
fVisibletrue
prototype properties
constructorfunction?TextObject
prototype
Writefunction?TextObject.prototype.Write
Writefunction?TextObject.prototype.Write
obj2
stHello,?world
prototype properties
constructorfunction?TextObject
prototype
Writefunction?TextObject.prototype.Write
fVisibletrue
Writefunction?ITOWrite
這個結(jié)構(gòu)存在兩個問題。一個是,當(dāng)每次構(gòu)造繼承的類的時候,基類的構(gòu)造函數(shù)都不會被調(diào)用。假如,構(gòu)造函數(shù)不做太多的事情,只是初始化一些成員變量為靜態(tài)的值,這個問題就不是太明顯了。第二個,注意,我將不能使用"function Obj.prototype.Method"的方式,來定義繼承類的成員。這是因為,對于構(gòu)造函數(shù)來說,我要把這些方法的定義,放入新創(chuàng)建的原型對象,而不是添加到,默認的原型對象。?

另一種子類繼承方式(An Alternate Subclassing Paradigm)

我們可以提出一種方法,更類似于反映C++類的概念和子類的定義,以及從子類反向存取基類的純原型鏈的風(fēng)格。它需要添加新的方法DeriveFrom給基類。
function Function.prototype.DeriveFrom(fnBase)<br><br><br><br>{<br><br><br><br>&nbsp;&nbsp;&nbsp; var prop;<br><br><br><br><br><br><br><br>&nbsp;&nbsp;&nbsp; if (this == fnBase)<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("Error - cannot derive from self");<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><br><br><br><br><br><br>&nbsp;&nbsp;&nbsp; for (prop in fnBase.prototype)<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (typeof(fnBase.prototype[prop]) == "function" &amp;&amp; !this.prototype[prop])<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.prototype[prop] = fnBase.prototype[prop];<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><br><br><br><br><br><br>&nbsp;&nbsp;&nbsp; this.prototype[fnBase.StName()] = fnBase;<br><br><br><br>}function Function.prototype.StName()<br><br><br><br>{<br><br><br><br>&nbsp;&nbsp;&nbsp; var st;<br><br><br><br><br><br><br><br>&nbsp;&nbsp;&nbsp; st = this.toString();<br><br><br><br>&nbsp;&nbsp;&nbsp; st = st.substring(st.indexOf(" ")+1, st.indexOf("("))<br><br><br><br><br><br><br><br>&nbsp;&nbsp;&nbsp; return st;<br><br><br><br>}function TextObject(st)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.st = st;<br><br>&nbsp;&nbsp;&nbsp; this.fVisible = true;<br><br>}<br><br> <br><br>function TextObject.prototype.Write()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; document.write('<br><br>' + this.st);<br><br>}<br><br> <br><br>function TextObject.prototype.IsVisible()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; return this.fVisible;<br><br>}<br><br> <br><br>function ItalicTextObject(st)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; this.TextObject(st);<br><br>}<br><br> <br><br>ItalicTextObject.DeriveFrom(TextObject);<br><br> <br><br>function ItalicTextObject.prototype.Write()<br><br>{<br><br>&nbsp;&nbsp;&nbsp; document.write('<br><br><em>' + this.st + '</em>');<br><br>}<br><br> <br><br>obj1 = new TextObject('Hello, mom');<br><br>obj2 = new ItalicTextObject('Hello, world');<br><br>obj1.Write();<br><br>obj2.Write();<br><br>
Hello, mom
Hello, world
obj1
stHello,?mom
fVisibletrue
prototype properties
constructorfunction?TextObject
prototype
Writefunction?TextObject.prototype.Write
IsVisiblefunction?TextObject.prototype.IsVisible
IsVisiblefunction?TextObject.prototype.IsVisible
Writefunction?TextObject.prototype.Write
obj2
stHello,?world
fVisibletrue
prototype properties
constructorfunction?ItalicTextObject
prototype
Writefunction?ItalicTextObject.prototype.Write
IsVisiblefunction?TextObject.prototype.IsVisible
TextObjectfunction?TextObject
prototype
Writefunction?TextObject.prototype.Write
IsVisiblefunction?TextObject.prototype.IsVisible
IsVisiblefunction?TextObject.prototype.IsVisible
TextObjectfunction?TextObject
prototype
Writefunction?TextObject.prototype.Write
IsVisiblefunction?TextObject.prototype.IsVisible
Writefunction?ItalicTextObject.prototype.Write
我們還得到了一個額外的好處,那就是,我們可以從多個基類進行繼承(多重的繼承)。

總結(jié)

以上是生活随笔為你收集整理的在Javascript中使用面向对象的编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。