從對象的建立到原型鏈

對象編程

對象的建立segmentfault

  對象字面量建立函數

  create方法ui

  構造函數this

原型鏈spa


對象.net

JavaScript的原始數據類型(primitive type)包括數字、字符串、布爾值、null和undefined(儘管typeof null爲object),其餘全部的值都是對象。prototype

對象是屬性的容器,其中每一個屬性擁有名字和值。屬性的名字可使包括空字符串在內的任意字符串。屬性值能夠是除undefined值以外的任何值。code

JavaScript包含一種原型鏈的特性,容許對象繼承另外一個對象的屬性。htm

對象的建立

對象字面量建立

這是一種直接建立新對象的方法。包圍在一對花括號中的零或多個「名/值」對即爲一個對象的字面量。

 1     var creature={};
 2     var animal={
 3         "first-name":"meow",
 4         sex:"male",
 5         age:"12",
 6         say:function () {
 7             return 'I am '+animal["first-name"];
 8         }
 9     }
10     console.log(animal.say()) ;//I am meow

注:

  1. 逗號用來分割「名/值」對。
  2. 屬性名是合法的JavaScript標識符且不是保留字,則不強求用引號括住屬性名。可是屬性名中的-是不合法的,如"first-name",因此引號是必須的,若是是first_name,引號則是可選的。
  3. 當屬性名不合法時,須要採用在[]後綴中括住一個字符串表達式的方式。如上面第7行。
  4. 當屬性爲函數時,稱其爲方法。如第六、10行。

create方法

每一個對象都鏈接到一個原型對象上,而且它可從中繼承屬性。全部經過字面量方式穿件的對象都鏈接到Object.prototype, 這是JavaScript的標配對象。

經過Object.create方法,使你建立一個新對象時,能夠選擇某個對象做爲它的原型。

 1 var animal={
 2         "first-name":"meow",
 3         age:"12",
 4         say:function () {
 5             return 'I am '+animal["first-name"];
 6         }
 7     }
 8     var dog=Object.create(animal);
 9     dog.name="dog";
10     dog.age=13;
11     dog.say=function () {
12             return 'I am a dog';
13     }
14     console.log(dog) ;

其中控制檯返回的dog的屬性如圖所示。這是一種「差別化繼承」。經過定製一個新對象,咱們指明它與所基於基本對象的區別。

當咱們對某個對象作出改變時,不會觸及該對象的原型,原型鏈接只有在檢索的時候纔會被用到。

但咱們嘗試獲取對象的某個屬性值,但該對象沒有此屬性名,那麼JavaScript會嘗試着從原型對象中獲取屬性值。若是原型對象也沒有,則從他的原型中尋找,以此類推,直到最後到達終點Object.prototype。這就是一條原型鏈。若是想要的屬性徹底不存在與原型鏈中,那麼結果就是undefined值。這個過程稱爲委託。

某屬性->對象屬性->原型屬性->原型的原型的屬性->....->Object.prototype。

構造器函數 

咱們還能夠經過構造器函數(constructor function)的方式來建立對象。使用這種方法來建立對象時,須要使用new操做符。

當一個函數對象被建立時,Function構造器產生的函數對象會爲其添加一個prototype屬性,this.prototype={constructor:this}。這個prototype的值是一個包含constructor屬性且屬性值爲該函數的對象。這個prototype對象時存放繼承特徵的地方。由於JavaScript沒有提供一種方法肯定哪一個函數是用在作構造器的,因此每一個函數都會獲得一個prototype對象

用構造函數建立的對象,其原型爲這個構造器函數的prototype對象。

使用構造器函數的好處之一是能夠再建立對象時接受一些參數。

 1 //建立一個名爲User的構造函數,它構造一個帶有name和age屬性的對象。
 2         function User(name,age){
 3             this.name = name;
 4             this.age = age;
 5         }
 6 //給User的全部實例提供一個名爲getName的公共方法
 7         User.prototype.getName = function(){//公有方法
 8               return this.name;
 9         }
10 //構造一個User實例    
11         var xiaoming= new User('小明',26);
12         console.log(xiaoming);//output:以下圖 

注:__proto__與prototype並不等價。__proto__是某個實例對象的屬性,而prototype則是屬於構造器函數的屬性。

注:爲了不漏掉new的狀況,構造器函數的命名方式須要採用首字母大寫的方式,而且這種方式只用來命名構造器函數。

原型鏈

原型自身具備對象固有的廣泛特徵,每一個對象有一個指向其原型對象的連接(即__proto__),經過這個連接咱們能夠再新建的對象中調用相關原型對象的方法和屬性,由此造成一條鏈,就是原型鏈。

原型鏈的造成是靠__proto__, 而非prototype。以下所示。引自JavaScript原型及原型鏈詳解

1 var animal = function(){};
2       var dog = function(){};
3     animal.price = 2000;
4     dog.prototype = animal;
5       var tidy = new dog();
6       console.log(dog.price) //undefined
7       console.log(tidy.price) // 2000  

執行dog.price的時候,發現沒有price這個屬性,雖然prototype指向的animal有這個屬性,但它並無去沿着這個「鏈」去尋找。一樣,執行tidy.price的時候,也沒有這個屬性,可是__proto__指向了animal,它會沿着這個鏈去尋找,animal中有price屬性,因此tidy.price輸出2000。由此得出,原型鏈的真正造成是靠的__proto__,而不是prototype。

 參考文獻:

《JavaScript語言精粹》

《JavaScript面向對象編程指南》

JavaScript原型及原型鏈詳解

js中__proto__和prototype的區別和關係?

爲何實例沒有prototype屬性?何時對象會有prototype屬性呢?

js面向對象之公有、私有、靜態屬性和方法詳解

相關文章
相關標籤/搜索