JavaScript中的所有事物都是對象,本文為大家介紹下JS中創建對象的幾種方式,如原始方法、工廠方法等等
JavaScript中的所有事物都是對象:字符串、數組、數值、函數等。JS中並沒有類的概念, 但我們可以利用JS的語法特征,以類的思想來創建對象。 原始方法 代碼如下: <script type="text/javascript"> var obj = new Object(); obj.name = "Koji"; //為對象添加屬性 obj.age = 21; obj.showName = function(){ //為對象添加方法 alert(this.name); } obj.showAge = function(){ alert(this.age); } obj.showName(); //Koji obj.showAge(); //21 </script> 上面的方式通過new關鍵字生成一個對象,然後根據JS是動態語言的特性添加屬性和方法,構 造一個對象。其中的this是表示調用該方法的對象。 這種方式的問題是如果需要多次創建對象,則需要重復代碼多次,不利於代碼的復用。 工廠方法 代碼如下: <script type="text/javascript"> function createObj(){ var obj = new Object(); //創建對象 obj.name = "Koji"; obj.age = 21; obj.showName = function(){ alert(this.name); } obj.showAge = function(){ alert(this.age); } return obj; //返回對象 } var obj1 = createObj(); var obj2 = createObj(); obj1.showName(); //Koji obj2.showAge(); //21 </script> 這種方式提高了代碼重用率,還可以改變工廠方法,傳入參數賦值。 代碼如下: <script type="text/javascript"> function createObj(name, age){ //構造對象時可以傳入初始化參數 var obj = new Object(); //創建對象 obj.name = name; obj.age = age; obj.showName = function(){ alert(this.name); } obj.showAge = function(){ alert(this.age); } return obj; //返回對象 } var obj1 = createObj("Koji", 22); var obj2 = createObj("Luo", 21); obj1.showName(); //Koji obj1.showAge(); //22 obj2.showName(); //Luo obj2.showAge(); //21 </script> 上面的方式雖然可以提高代碼的復用率,但和面向對象中類的概念相比有一個很大的缺陷。面 相對象強調對象的屬性私有,而對象的方法是共享的。而上面的工廠方法創建對象的時候要為每個 對象創建各自私有的方法。同時由於為每個對象都創建邏輯相同的方法,浪費內存。改進如下 代碼如下: <span style="font-size:14px;"><script type="text/javascript"> function createObj(name, age){ var obj = new Object(); //創建對象 obj.name = name; obj.age = age; obj.showName = showName; obj.showAge = showAge; return obj; //返回對象 } function showName(){ //函數也是一個對象 alert(this.name); } function showAge(){ alert(this.age); } var obj1 = createObj("Koji", 22); var obj2 = createObj("Luo", 21); obj1.showName(); //Koji obj1.showAge(); //22 obj2.showName(); //Luo obj2.showAge(); //21 </script></span> 上面通過定義連個函數對象,解決了不同對象持有函數對象的私有問題。現在所有對象的方法都 持有上面兩個函數的引用。但這麼一來的話,對象的函數又和對象成了相互獨立,不相干的了。這和 面向對象中特定方法屬於特定類的思想不符合。 構造函數方式 代碼如下: <script type="text/javascript"> //定義一個構造函數,用來生成對應的對象,可以類比Java中的構造函數 function Person(name, age){ //當調用new Person的時候,在執行第一行代碼前,先生成一個Person對象,並將對象在內存中的 //索引賦值給this關鍵字,此時可以通過this關鍵字操作新生成的對象,如下面的添加屬性或方法 this.name = name; //this關鍵字不能少。為當前對象,即this關鍵字引用的對象的name屬性賦值 //,實際相當於為當前對象添加name屬性後,再為其name屬性賦值。 this.age = age; this.showName = function(){ //為當前對象添加方法 alert(this.name); } this.showAge = function(){ alert(this.age); } //將當前對象返回給賦值符號左邊的變量(不必明確使用return) } var obj1 = new Person("Koji", 22); //生成一個Person對象 var obj2 = new Person("Luo", 21); obj1.showName(); //Koji obj1.showAge(); //22 obj2.showName(); //Luo obj2.showAge(); //21 </script> 構造函數的方式和工廠方式一樣,會為每個對象創建獨享的函數對象。當然也可以將這些函數 對象定義在構造函數外面,這樣又有了對象和方法相互獨立的問題。 原型方法:該方法利用的對象的prototype屬性 代碼如下: script type="text/javascript"> function Person(){} //定義一個空構造函數,且不能傳遞參數 //將所有的屬性的方法都賦予prototype屬性 Person.prototype.name = "Koji"; //添加屬性 Person.prototype.age = 22; Person.prototype.showName = function(){ //添加方法 alert(this.name); } Person.prototype.showAge = function(){ alert(this.age); } var obj1 = new Person(); //生成一個Person對象 var obj2 = new Person(); obj1.showName(); //Koji obj1.showAge(); //22 obj2.showName(); //Koji obj2.showAge(); //22 </script> 當生成Person對象的時候prototype的屬性都賦值給了新的對象。那麼屬性和方法是共享的。 該方法的問題首先是構造函數不能傳參,每個新生成的對象都有默認值。其次,方法共享沒有 任何問題,但是屬性共享就有問題,當屬性是可改變狀態的對象的時候。 代碼如下: <script type="text/javascript"> function Person(){} //定義一個空構造函數,且不能傳遞參數 Person.prototype.age = 22; Person.prototype.array = new Array("Koji", "Luo"); Person.prototype.showAge = function(){ alert(this.age); } Person.prototype.showArray = function(){ alert(this.array); } var obj1 = new Person(); //生成一個Person對象 var obj2 = new Person(); obj1.array.push("Kyo"); //向obj1的array屬性添加一個元素 obj1.showArray(); //Koji,Luo,Kyo obj2.showArray(); //Koji,Luo,Kyo </script> 上面的代碼通過obj1向obj1的屬性array添加元素的時候,obj2的arra屬性的元素也跟著受到 影響,原因就在於obj1和obj2對象的array屬性引用的是同一個Array對象,那麼改變這個Array 對象,另一引用該Array對象的屬性自然也會受到影響 混合的構造函數/原型方式 使用構造函數定義對象的屬性,使用原型(prototype)定義對象的方法,這樣就可以做到屬性 私有,而方法共享。 代碼如下: <script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; this.array = new Array("Koji", "Luo"); } Person.prototype.showName = function() { alert(this.name); } Person.prototype.showArray = function() { alert(this.array); } var obj1 = new Person("Koji", 22); //生成一個Person對象 var obj2 = new Person("Luo", 21); obj1.array.push("Kyo"); //向obj1的array屬性添加一個元素 obj1.showArray(); //Koji,Luo,Kyo obj1.showName(); //Koji obj2.showArray(); //Koji,Luo obj2.showName(); //Luo </script> 屬性私有後,改變各自的屬性不會影響別的對象。同時,方法也是由各個對象共享。在語義上, 這符合了面相對象編程的要求。 動態原型方法 代碼如下: <script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; this.array = new Array("Koji", "Luo"); //如果Person對象中的_initialized為undefined,表明還沒有為Person的原型添加方法 if (typeof Person._initialized == "undefined") { Person.prototype.showName = function() { alert(this.name); } Person.prototype.showArray = function() { alert(this.array); } Person._initialized = true; //設置為true,不必再為prototype添加方法 } } var obj1 = new Person("Koji", 22); //生成一個Person對象 var obj2 = new Person("Luo", 21); obj1.array.push("Kyo"); //向obj1的array屬性添加一個元素 obj1.showArray(); //Koji,Luo,Kyo obj1.showName(); //Koji obj2.showArray(); //Koji,Luo obj2.showName(); //Luo </script> 這種方法和構造函數/原型方式大同小異。只是將方法的添加放到了構造函數之中,同時在構造 函數Person上添加了一個屬性用來保證if語句只能成功執行一次 在實際應用中采用最廣泛的是構造函數/原型方法。動態原型方法也很流行,它在功能上和構造 函數/原型方法是等價的。不要單獨使用構造函數或原型方法。 詳細出處參考:http://www.jb51.net/article/46249.htm