欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JavaScript基于面向?qū)ο笾畡?chuàng)建對(duì)象(2)

 更新時(shí)間:2015年12月10日 11:05:41   作者:丿木呈廣予口貝  
這篇文章主要介紹了JavaScript基于面向?qū)ο笾畡?chuàng)建對(duì)象,詳細(xì)的分析面向?qū)ο蟮脑头绞揭约捌渌C合的方式,感興趣的小伙伴們可以參考一下

接著上文《詳解JavaScript基于面向?qū)ο笾畡?chuàng)建對(duì)象(1)》繼續(xù)學(xué)習(xí)。

4、原型方式
       我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè)通過(guò)prototype(原型)屬性,這個(gè)屬性是一個(gè)對(duì)象,它的用途是包含可以由特定類(lèi)型的所有實(shí)例共享的屬性和方法。邏輯上可以這么理解:prototypt通過(guò)條用構(gòu)造函數(shù)而創(chuàng)建的那個(gè)對(duì)象的原型對(duì)象。使用原型的好處就是可以讓所有對(duì)象實(shí)例共享它所包含的屬性和方法。也就是說(shuō),不必在構(gòu)造函數(shù)中定義對(duì)象信息,而是直接將這些信息添加到原型中。
       原型方式利用了對(duì)象的prototype 屬性,可以把它看成創(chuàng)建新對(duì)象所依賴(lài)的原型。這里,首先用空構(gòu)造函數(shù)來(lái)設(shè)置函數(shù)名。然后所有的屬性和方法都被直接賦予prototype屬性。我重寫(xiě)了前面的例子,代碼如下:

function Car() { }; 
//將所有的屬性的方法都賦予prototype屬性 
Car.prototype.color = "blue"; 
Car.prototype.doors = 4; 
Car.prototype.mpg = 25; 
Car.prototype.showColor = function() { 
  return this.color; 
}; 
var Car1 = new Car(); 
var Car2 = new Car(); 
document.write(Car1.showColor()+"<br/>");//輸出:blue 
document.write(Car2.showColor());//輸出:blue 

      在這段代碼中,首先定義構(gòu)造函數(shù)Car(),其中無(wú)任何代碼。接下來(lái)的幾行代碼,通過(guò)給Car的 prototype 屬性添加屬性去定義Car對(duì)象的屬性。調(diào)用new Car()時(shí),原型的所有屬性都被立即賦予要?jiǎng)?chuàng)建的對(duì)象,意味著所有Car實(shí)例存放的都是指向 showColor() 函數(shù)的指針。從語(yǔ)義上講,所有屬性看起來(lái)都屬于一個(gè)對(duì)象,因此解決了前面的工廠方式和構(gòu)造函數(shù)方式存在的問(wèn)題。
       此外,使用這種方式,還能用 instanceof 運(yùn)算符檢查給定變量指向的對(duì)象的類(lèi)型:

復(fù)制代碼 代碼如下:
<span style="font-size:18px;">document.write(Car1 instanceof Car);    //輸出:true</span> 

      原型方式看起來(lái)是個(gè)不錯(cuò)的解決方案。遺憾的是,它并不盡如人意。首先,這個(gè)構(gòu)造函數(shù)沒(méi)有參數(shù)。使用原型方式,不能通過(guò)給構(gòu)造函數(shù)傳遞參數(shù)來(lái)初始化屬性的值,因?yàn)镃ar1和Car2的color屬性都等于 "blue",doors屬性都等于4,mpg屬性都等于25。這意味著必須在對(duì)象創(chuàng)建后才能改變屬性的默認(rèn)值,這點(diǎn)很令人討厭,但還沒(méi)完。真正的問(wèn)題出現(xiàn)在屬性指向的是對(duì)象,而不是函數(shù)時(shí)。函數(shù)共享不會(huì)造成問(wèn)題,但對(duì)象卻很少被多個(gè)實(shí)例共享。請(qǐng)思考下面的例子:

function Car() { };//定義一個(gè)空構(gòu)造函數(shù),且不能傳遞參數(shù) 
Car.prototype.color = "blue"; 
Car.prototype.doors = 4; 
Car.prototype.mpg = 25; 
Car.prototype.drivers = new Array("Mike","John"); 
Car.prototype.showColor = function() { 
  return this.color; 
}; 
var Car1 = new Car(); 
var Car2 = new Car(); 
Car1.drivers.push("Bill"); 
document.write(Car1.drivers+"<br/>");//輸出:Mike,John,Bill 
document.write(Car2.drivers);//輸出 :Mike,John,Bill 

       上面的代碼中,屬性drivers是指向Array對(duì)象的指針,該數(shù)組中包含兩個(gè)名"Mike"和 "John"。由于 drivers是引用值,Car的兩個(gè)實(shí)例都指向同一個(gè)數(shù)組。這意味著給Car1.drivers添加值 "Bill",在 Car2.drivers 中也能看到。輸出這兩個(gè)指針中的任何一個(gè),結(jié)果都是顯示字符串 "Mike,John,Bill"。由于創(chuàng)建對(duì)象時(shí)有這么多問(wèn)題,你一定會(huì)想,是否有種合理的創(chuàng)建對(duì)象的方法呢?答案是有,需要聯(lián)合使用構(gòu)造函數(shù)和原型方式。
5、混合的構(gòu)造函數(shù)/原型方式(推薦使用)
       混合使用構(gòu)造函數(shù)方式和原型方式,就可像用其他程序設(shè)計(jì)語(yǔ)言一樣創(chuàng)建對(duì)象。這種概念非常簡(jiǎn)單,即用構(gòu)造函數(shù)定義對(duì)象的所有非函數(shù)屬性,用原型方式定義對(duì)象的函數(shù)屬性(方法)。結(jié)果是,所有函數(shù)都只創(chuàng)建一次,而每個(gè)對(duì)象都具有自己的對(duì)象屬性實(shí)例。我們重寫(xiě)了前面的例子,代碼如下:

function Car(Color,Doors,Mpg) { 
 this.color = Color; 
 this.doors = Doors; 
 this.mpg = Mpg; 
 this.drivers = new Array("Mike","John"); 
}; 
Car.prototype.showColor = function() { 
   return this.color; 
}; 
var Car1 = new Car("red",4,23); 
var Car2 = new Car("blue",3,25); 
Car1.drivers.push("Bill"); 
document.write(Car1.drivers+"<br/>");//輸出:Mike,John,Bill 
documnet.write(Car2.drivers);//輸出:Mike,John 

       現(xiàn)在就更像創(chuàng)建一般對(duì)象了。所有的非函數(shù)屬性都在構(gòu)造函數(shù)中創(chuàng)建,意味著又能夠用構(gòu)造函數(shù)的參數(shù)賦予屬性默認(rèn)值了。因?yàn)橹粍?chuàng)建showColor()函數(shù)的一個(gè)實(shí)例,所以沒(méi)有內(nèi)存浪費(fèi)。此外,給Car1的drivers數(shù)組添加 "Bill" 值,不會(huì)影響到Car2的數(shù)組,所以輸出這些數(shù)組的值時(shí),Car1.drivers 顯示的是 "Mike,John,Bill",而 Car2.drivers 顯示的是 "Mike,John"。因?yàn)槭褂昧嗽头绞?,所以仍然能利?instanceof運(yùn)算符來(lái)判斷對(duì)象的類(lèi)型。
       這種方式是ECMAScript采用的主要方式,它具有其他方式的特性,卻沒(méi)有他們的副作用。不過(guò),有些開(kāi)發(fā)者仍覺(jué)得這種方法不夠完美。
6、動(dòng)態(tài)原型方式
      對(duì)于習(xí)慣使用其他語(yǔ)言的開(kāi)發(fā)者來(lái)說(shuō),使用混合的構(gòu)造函數(shù)/原型方式感覺(jué)不那么和諧。畢竟,定義類(lèi)時(shí),大多數(shù)面向?qū)ο笳Z(yǔ)言都對(duì)屬性和方法進(jìn)行了視覺(jué)上的封裝。請(qǐng)考慮下面的 Java 類(lèi):

class Car { 
 public String color = "blue"; 
 public int doors = 4; 
 public int mpg = 25; 
 public Car(String color, int doors, int mpg) { 
  this.color = color; 
  this.doors = doors; 
  this.mpg = mpg; 
 } 
 public void showColor() { 
  System.out.println(color); 
 } 
} 

        Java很好地打包了Car類(lèi)的所有屬性和方法,因此看見(jiàn)這段代碼就知道它要實(shí)現(xiàn)什么功能,它定義了一個(gè)對(duì)象的信息。批評(píng)混合的構(gòu)造函數(shù)/原型方式的人認(rèn)為,在構(gòu)造函數(shù)內(nèi)部找屬性,在其外部找方法的做法不合邏輯。因此,他們?cè)O(shè)計(jì)了動(dòng)態(tài)原型方法,以提供更友好的編碼風(fēng)格。
       動(dòng)態(tài)原型方法的基本想法與混合的構(gòu)造函數(shù)/原型方式相同,即在構(gòu)造函數(shù)內(nèi)定義非函數(shù)屬性,而函數(shù)屬性則利用原型屬性定義。唯一的區(qū)別是賦予對(duì)象方法的位置。下面是用動(dòng)態(tài)原型方法重寫(xiě)的Car:

function Car(Color,Doors,Mpg) { 
 this.color = Color; 
 this.doors = Doors; 
 this.mpg = Mpg; 
 this.drivers = new Array("Mike","John"); 
 //如果Car對(duì)象中的_initialized為undefined,表明還沒(méi)有為Car的原型添加方法 
 if (typeof Car._initialized == "undefined") { 
   Car.prototype.showColor = function() { 
    return this.color; 
   }; 
   Car._initialized = true; //設(shè)置為true,不必再為prototype添加方法 
 } 
} 
var Car1 = new Car("red",4,23);//生成一個(gè)Car對(duì)象 
var Car2 = new Car("blue",3,25); 
Car1.drivers.push("Bill");//向Car1對(duì)象實(shí)例的drivers屬性添加一個(gè)元素 
document.write(Car1.drivers+"<br/>");//輸出:Mike,John,Bill 
document.write(Car2.drivers);//輸出:Mike,John 

       直到檢查typeof Car._initialize是否等于"undefined"之前,這個(gè)構(gòu)造函數(shù)都未發(fā)生變化。這行代碼是動(dòng)態(tài)原型方法中最重要的部分。如果這個(gè)值未定義,構(gòu)造函數(shù)將用原型方式繼續(xù)定義對(duì)象的方法,然后把 Car._initialized設(shè)置為true。如果這個(gè)值定義了(它的值為 true時(shí),typeof 的值為Boolean),那么就不再創(chuàng)建該方法。簡(jiǎn)而言之,該方法使用標(biāo)志(_initialized)來(lái)判斷是否已給原型賦予了任何方法。該方法只創(chuàng)建并賦值一次,傳統(tǒng)的 OOP開(kāi)發(fā)者會(huì)高興地發(fā)現(xiàn),這段代碼看起來(lái)更像其他語(yǔ)言中的類(lèi)定義了。
       我們應(yīng)該采用哪種方式呢?
       如前所述,目前使用最廣泛的是混合的構(gòu)造函數(shù)/原型方式。此外,動(dòng)態(tài)原型方式也很流行,在功能上與構(gòu)造函數(shù)/原型方式等價(jià)??梢圆捎眠@兩種方式中的任何一種。不過(guò)不要單獨(dú)使用經(jīng)典的構(gòu)造函數(shù)或原型方式,因?yàn)檫@樣會(huì)給代碼引入問(wèn)題。總之JS是基于面向?qū)ο蟮囊婚T(mén)客戶(hù)端腳本語(yǔ)言,我們?cè)趯W(xué)習(xí)它的面向?qū)ο蠹夹g(shù)的時(shí)候要的留意JS與其他嚴(yán)謹(jǐn)性高的程序語(yǔ)言的不同。也要正確使用JS創(chuàng)建對(duì)象的合理的方式,推薦使用構(gòu)造函數(shù)與原型方式的混合方式創(chuàng)建對(duì)象實(shí)例。這樣可以避免許多不必要的麻煩。

以上就是JavaScript基于面向?qū)ο笾畡?chuàng)建對(duì)象的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

相關(guān)文章

最新評(píng)論