国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript構造器理解

PiscesYE / 1289人閱讀

摘要:類類的概念應該是面向對象語言的一個特色,但是并不像,等高級語言那樣擁有正式的類,而是多數通過構造器以及原型方式來仿造實現。因此,出現了構造函數方式,它的關鍵在于構造器概念的引入。于是,這就產生了構造函數原型法的類構造方法。

  

類 Class 類的概念應該是面向對象語言的一個特色,但是JavaScript并不像Java,C++等高級語言那樣擁有正式的類,而是多數通過構造器以及原型方式來仿造實現。在討論構造器和原型方法前,我可以看看一種叫做工廠方式的仿造方法。

工廠模式



這種方式顯然可以實現class的功能,但是外形上怎么也無法說它是個class以及class實例的創建過程。因此,出現了“構造函數方式”,它的關鍵在于構造器(Constructor)概念的引入。

構造函數方式

構造器(Constructor)



這個看起來有點類的樣子了吧(先不提那個難看的外置function)?我們發現,那個constructor其實就是一個簡單的function,它與“工廠方式”中的createCar()區別就在于:
1、方法名大寫
2、沒有了空對象的創建和返回
3、使用this做引用。
那原來的那個空對象的創建以及返回的步驟去哪了呢?這兩個步驟,現在都由創建實例時的“new”實現了。“new”這個操作符負責創建一個空對象,然后將那個叫做構造器的function添加到實例對象中并觸發它,這樣這個function實際上就是這個對象的一個method,function中的this指向的便是這個對象,最后將這個對象返回。根據如上分析,我們可以把這個過程簡單分解為如下代碼:


構造函數方式雖然與高級面向對象語言中的類創建方式已經很接近(使用new創建),但是貌似那個游離在類之外的function material()其實卻是個相當有礙觀瞻的瑕疵。我們應該想一種辦法讓這個方法與類掛鉤,讓它成為類的一個屬性,不是全局的。于是,這就產生了“構造函數+原型法”的類構造方法。

構造函數 + 原型

從上面的構造函數模式創建對象的例子上可以看到,每創建一個對象實例,每個對象中都有material()這個成員方法,這樣看起來是不是會浪費內存空間,降低執行效率。所以JavaScript中提供了原型的方法可以解決這個問題。

  

原型:proto
在JavaScript中每個函數都有一個原型屬性,即prototype,當調用構造函數進行創建對象的時候,所有該構造函數原型的屬性在創建的對象上都可用。按照這樣的想法多個CreateCar都可以共享一個原型material.

構造函數+原型法中,我們對于類的method期待得到的效果是:
1. 僅是類的method而不是全局的。
2. 只在類被定義時創建一個method實例,然后被所有類的實例共用。

由這兩個目標,我們很容易想到高級面向對象語言Java的private static變量的特點。JavaScript沒有為我們提供這么簡單的符號來實現這個復雜功能,但是卻有一個屬性可以幫我們仿造出這種效果:prototype。我們先來看幾段prototype的使用代碼。


> function Car(){ } > > Car.prototype.material = "steel"; > > var car1 = new Car(); var car2 = new Car(); > > document.write(car1.material); //prints "steel" > document.write(car2.material); //prints "steel" > > //car1.prototype.material = "iron" //compile error:car1.prototype is > undefined car1.material = "iron"; > > document.write(car1.material); //prints "iron" > document.write(car2.material); //prints "steel" > document.write(Car.prototype.material); //prints "steel" > > Car.prototype.material = "wood"; var car3 = new Car(); > document.write(car1.material); //prints "iron" > document.write(car2.material ); //prints "wood" > document.write(car3.material ); //prints "wood" > document.write(Car.prototype.material); //prints "wood"

分析該段代碼前,需要明確兩個概念:對象的直屬屬性和繼承屬性。直接在構造函數中通過this.someproperty = xxx這種形式定義的someproperty屬性叫做對象的直屬屬性,而通過如上第4行代碼那樣Car.prototype.material = "steel";這種形式定義的material屬性叫做繼承屬性。由上面這段代碼,我們可以總結出prototype屬性的如下特點:

prototype是function下的屬性(其實任意object都擁有該屬性,function是對象的一種)

prototype屬性的值是一個對象,因此可任意添加子屬性(line 4)

類的實例可以直接通過"."來直接獲取prototype下的任意子屬性(line 9)

所有以此function作為構造函數創建的類實例共用prototype中的屬性及值(ling 9,10)

類的實例沒有prototype屬性(line 12)

可以直接通過 "實例.屬性 = xxx" 的方式修改繼承屬性,修改后的值將覆蓋繼承自prototype的屬性,但此修改不影響prototype本身,也不影響其它類實例(line 15,16,17)

繼承屬性修改后,該屬性就成為類實例的直屬屬性

可以直接修改prototype的屬性值,此改變將作用于此類下的所有實例,但無法改變直屬屬性值(極晚綁定line 21-24)

  

PS:對象實例在讀取某屬性時,如果在本身的直屬屬性中沒有查找到該屬性,那么就會去查找function下的prototype的屬性。

Tip:我們可以通過hasOwnProperty方法來判斷某屬性是直屬于對象還是繼承自它的prototype屬性
    car1.hasOwnProperty("material"); // true
    car2.hasOwnProperty("material"); // false
    "material" in car2;// true

構造函數+原型方式代碼如下



這個跟高級面向對象語言中的class的樣子更~加類似了吧?上述寫法只是在“語義”上達到了對類屬性和方法的封裝,很多面向對象思想的完美主義者希望在“視覺”上也達到封裝,因此就產生了“動態原型法”,請看下面的代碼:

function Car(color, title){
   this.color = color;
   this.title = title;
   if (typeof Car._initialized == "undefined") {
      Car.prototype.start = function(){
          alert("Bang!!!");
      };
      Car.prototype.material = "steel";
      Car._initialized = true;
   }
}

我們看,其實Car.prototype的屬性定義是可以被放進Car function的定義之中的,這樣就達到了“視覺”封裝。但是我們沒有單純的move,我們需要加一個條件,讓這些賦值操作只執行一次,而不是每次創建對象實例的時候都執行,造成內存空間的浪費。添加_initialized 屬性的目的就在于此。

  

對于所有用字面量創建的對象而言,其prototype對象均為Object.prototype(作為一個特殊對象,Object.prototype沒有原型對象):

var x = {a:18, b:28};

console.log(x.__proto__);//Object {}

  

而對于所有用new操作符創建的對象而言,其prototype對象均為constructor函數的prototype屬性:



var x = {a:18, b:28}; function Test(c){ this.c = c; } Test.prototype = x; var t = new Test(38); console.log(t);//Object {c=38, a=18, b=28} console.log(t.__proto__);//Object {a=18, b=28} console.log(t.__proto__.__proto__);//Object {}
  

總結出來一句話就是:用構造函數方式定義對象的所有非函數屬性,用原型方式定義對象的函數屬性。


整理于:
http://dbear.iteye.com/blog/613745
http://www.cnblogs.com/tomxu/archive/2012/02/21/2352994.html

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85657.html

相關文章

  • 面向對象的 JavaScript

    摘要:是完全的面向對象語言,它們通過類的形式組織函數和變量,使之不能脫離對象存在。而在基于原型的面向對象方式中,對象則是依靠構造器利用原型構造出來的。 JavaScript 函數式腳本語言特性以及其看似隨意的編寫風格,導致長期以來人們對這一門語言的誤解,即認為 JavaScript 不是一門面向對象的語言,或者只是部分具備一些面向對象的特征。本文將回歸面向對象本意,從對語言感悟的角度闡述為什...

    novo 評論0 收藏0
  • 理解javascript核心知識點

    摘要:作用域鏈的作用就是做標示符解析。事件循環還有個明顯的特點單線程。早期都是用作開發,單線程可以比較好當規避同步問題,降低了開發門檻。單線程需要解決的是效率問題,里的解決思想是異步非阻塞。 0、前言 本人在大學時非常癡迷java,認為java就是世界上最好的語言,偶爾在項目中會用到一些javascript,但基本沒放在眼里。較全面的接觸javascript是在實習的時候,通過這次的了解發現...

    laznrbfe 評論0 收藏0
  • 講清楚之 javascript原形

    摘要:構造函數和實例都通過屬性指向了原形。代碼示例是構造函數的實例的屬性與的屬性保存的值相等,即他們指向同一個對象原形。 講清楚之javascript原型 標簽: javascript javascript 中原形是一個比較難于理解的概念。javascript 權威指南在原形這一章也花了大量的篇幅進行介紹,也許你已經讀過javascript 權威指南,或者已經是讀第N篇了,然而這篇文章的目...

    高勝山 評論0 收藏0
  • 深入理解JavaScript原型與繼承

    摘要:深入理解原型與繼承看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 深入理解:JavaScript原型與繼承 看過不少書籍,不少文章,對于原型與繼承的說明基本上讓人不明覺厲,特別是對于習慣了面向對象編程的人來說更難理解,這里我就給大家說說我的理解。 首先JavaScript是一門基于原型編程的語言...

    mengbo 評論0 收藏0
  • JavaScript 工廠函數 vs 構造函數

    摘要:當談到語言與其他編程語言相比時,你可能會聽到一些令人困惑東西,其中之一是工廠函數和構造函數。好的,讓我們用構造函數做同樣的實驗。當我們使用工廠函數創建對象時,它的指向,而當從構造函數創建對象時,它指向它的構造函數原型對象。 showImg(https://segmentfault.com/img/bVbr58T?w=1600&h=900); 當談到JavaScript語言與其他編程語言...

    RayKr 評論0 收藏0

發表評論

0條評論

PiscesYE

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<