前言: 這篇教程是由Tim Scarfe 著,由javascriptKit.com 編輯目錄結構.
在寫面向對象的WEB應用程序方面JavaSciprt是一種很好的選擇.它能支持OOP.因為它通過原型支持繼承的方式和通過屬性和方法的方式一樣好.很多開發者試圖拋棄JS,試著用C#或JAVA僅是因為JS不是他認為合適的面向對象的語言.許多人還沒有認識到javascript支持繼承.當你寫面向對象的代碼時.它能給你很強大的能量.你也可以使用它寫出可復用,可封裝的代碼.
對象為何如此偉大?
面向對象思想的成功是由于它仿照了現實中的事物和事物的聯系.事物有屬性和方法.如果我們描述一個臺燈.我們會說它的高度和寬度,比如12CM."開燈"這個動作是它的方法.當它是處于開著的狀態時.它可以被調亮一點或暗一點(也就是亮度這個屬性值變大或變小).
javascript 給予了為WEB應用程序創建對象的能力.對象在需要的時候相應的事件會被觸發,代碼封裝后,它能被實例化很多次.
用 new Object() 來創建對象
在javascript里有幾種創建對象的方法,在不同的場合可用不同的方法.最簡單的就是用 new 操作符,例如:
<script language="javascript" type="text/javascript">
<!--
person = new Object()
person.name = "Tim Scarfe"
person.height = "6Ft"
person.run = function() {
this.state = "running"
this.speed = "4ms^-1"
}
//-->
</script>
我們在這個例子里定義了person這個對象,然后加入了它的屬性和方法.在這個例子里,自定義的方法里有兩個屬性.
用文字記號Literal Notation創建對象
用文字記號也可以創建對象,但要javascript 1.2以上版本.它的創建形式是多樣的.
<script language="javascript" type="text/javascript">
<!--
// Object Literals
timObject = {
property1 : "Hello",
property2 : "MmmMMm",
property3 : ["mmm", 2, 3, 6, "kkk"],
method1 : function(){alert("Method had been called" + this.property1)}
};
timObject.method1();
alert(timObject.property3[2]) // will yield 3
var circle = { x : 0, y : 0, radius: 2 } // another example
// nesting is no problem.
var rectangle = {
upperLeft : { x : 2, y : 2 },
lowerRight : { x : 4, y : 4}
}
alert(rectangle.upperLeft.x) // will yield 2
//-->
</script>
文字記號可是是數組,也可以是任意的javascript表達式或值.
用 new 操作符或文字記號創建一個自定義對象都是簡單的,也是符合邏輯的.但它最大的缺點就是結果不可復用.也不能很容易的用不同的版本初始化創建對象.例如上面的第一個例子,如果 person 的 name 不是 "Tim Scarfe",那樣我們不得不重新定義整個對象,僅僅為了適應它的一點點改變.
對象的構造和原型
在OOP的世界里,用先前的方法定義對象在許多場合都有限制.我們需要一種創建對象的方法,類型可以被多次使用而不用重新定義.對象在實例化時每次都可以按需分配不同的值.實現這個目標的標準方法是用對象構造器函數.
一個對象構造器只不過是個有規則的javascript函數,它就象一個容器(定義參數,調用其他函數等等).它們兩者所不同的是構造器函數是由 new 操作符調用的.(你將在下面的例子中看到).基于函數語法形式的對象定義,我們可以使它工作得最好.
讓我們用現實世界中的貓來舉個例子.貓的 name 和 color 是貓的屬性.meeyow(貓叫)是它的一個方法.重要的是任何不同的貓都可能有不同的 name 和 meeyow 的叫聲.為了建立適應這些特征的對象類,我們將使用對象構造器.
<script language="javascript" type="text/javascript">
<!--
function cat(name) {
this.name = name;
this.talk = function() {
alert( this.name + " say meeow!" )
}
}
cat1 = new cat("felix")
cat1.talk() //alerts "felix says meeow!"
cat2 = new cat("ginger")
cat2.talk() //alerts "ginger says meeow!"
//-->
</script>
在這里,函數 cat() 是一個對象構造器,它的屬性和方法在函數體里用this來定義,用對象構造器定義的對象用 new 來實例化.主意我們如何非常容易的定義多個cat 的實例.每一個都有自己的名字,這就是對象構造器帶給我們的靈活性.
構造器建立了對象的藍圖.并不是對象本身.
在原型里增加方法.
在上面我們看到的例子里,對象的方法是在構造器里定義好的了.另外一種實現的途徑是通過原型(prototype).xxx
原型是javascript繼承的一種形式.我們可以為對象定義好后,再創造一個方法.原來所有對象的實例都將共享.
讓我們來擴展最初的 cat 對象.增加一個改名的方法.用 prototype 的方式.
<script language="javascript" type="text/javascript">
<!--
cat.prototype.changeName = function(name) {
this.name = name;
}
firstCat = new cat("pursur")
firstCat.changeName("Bill")
firstCat.talk() //alerts "Bill says meeow!"
//-->
</script>
就象你所看到的.我們僅只用了 關鍵字 prototype 實現了在對象定義后馬上增加了changeName方法.這個方法被所有的實例共享.
用原型(prototype) 重載 javascript 對象
原型 在自定義對象和有選擇性的重載對象上都可以工作.比如 Date() 或 String
這可能是無止境的.
子類和超類
在JAVA 和C++里,有關于類層次的外在概念.每一個類能有一個角色.
In Java and C++, there is an explicit concept of the class hierarchy. i.e. Every class can have a super class from which it inherits properties and methods. Any class can be extended, or sub-classed so the resulting subclass can inherit its parent's behavior. As we have seen, javascript supports prototype inheritance instead of class based. It's possible for inheritance to happen other ways, however.
The following is an example of inheritance through functions.
下面一個例子演示了如何繼承通過function .
<script language="javascript" type="text/javascript">
<!--
// thanks to webreference
function superClass() {
this.supertest = superTest; //attach method superTest
}
function subClass() {
this.inheritFrom = superClass;
this.inheritFrom();
this.subtest = subTest; //attach method subTest
}
function superTest() {
return "superTest";
}
function subTest() {
return "subTest";
}
var newClass = new subClass();
alert(newClass.subtest()); // yields "subTest"
alert(newClass.supertest()); // yields "superTest"
//-->
</script>
基于繼承的原型是遙遠的.為 javascript 應用程序在許多場合.
(基于原型的繼承在許多javascript的應用場合是非常有用的.)
對象作為聯合數組
正如你所知, (.)操作符能夠用來存儲.[] 操作符用來操作數組.
<script language="javascript" type="text/javascript">
<!--
// These are the same
object.property
object["property"]
//-->
</script>
<SCRIPT LANGUAGE="javascript">
<!--
function Circle (xPoint, yPoint, radius) {
this.x = xPoint;
this.y = yPoint;
this.r = radius;
}
var aCircle = new Circle(5, 11, 99);
alert(aCircle.x);
alert(aCircle["x"]);
//-->
</SCRIPT>
How do I loop through properties in an object?
You need to use a for/in loop.
我們可以通過for in循環來遍歷對象的屬性。
<script language="javascript" type="text/javascript">
<!--
var testObj = {
prop1 : "hello",
prop2 : "hello2",
prop3 : new Array("hello",1,2)
}
for(x in testObj) alert( x + "-" + testObj[ x ] )
//-->
</script>
<SCRIPT LANGUAGE="javascript">
<!--
var Circle = { x : 0, y : 1, radius: 2 } // another example
for(p in Circle)
alert( p + "-" + Circle[ p ] )
//-->
</SCRIPT>
The important thing to notice is that in the object syntax the property is an identifier, whereas in the array syntax, it's a string. The obvious benefits of using an array syntax to aclearcase/" target="_blank" >ccess an object is because of the literal data type, you can easily concat strings and play around with them to access an object. For this to work with the standard syntax, an eval() would need to be used.
應該值得注意的是對象的屬性只是一個標識字符,盡管在一個數組里是一個字符串,因為是一個literal的數據類型,所以有利于使用數組的方式的操作一個對象。你也可以很容易的存取一個對象在標準的語句中。這個時候eval()函數可能用得到。
<script language="javascript" type="text/javascript">
<!--
testObj = {
prop1 : "hello",
prop2 : "hello2",
prop3 : new Array("helloa",1,2)
}
for(x in testObj) alert( x + "-" + testObj[ x ] )
var prop3 = testObj["prop3"];
alert(prop3);
//alert(prop[1]);
alert(typeof(prop3));
alert(eval(prop3)[1]);
alert(typeof(eval(prop3)[1]));
//-->
</script>