DIV CSS 佈局教程網

Javascript原型鉤沉
編輯:JavaScript基礎知識     

寫在前面的總結:

JS當中創建一個對象有好幾種方式,大體上就是以下幾種:

①通過var obj ={...}

這種方式一般稱為字面量方式,{}直接寫需要定義的字段

②var obj = new Object()

Object對象是JS的內建對象

③通過構造函數創建對象

例如:

function father(){
this.name = "I'm your father!"
}
var f = new father();

這裡通過構造函數的方式創建了一個對象實例f

④通過Object.create創建對象

Object.create(proto [, propertiesObject ]) 是E5中提出的一種新的對象創建方式,第一個參數是要繼承的原型,如果不是一個子函數,可以傳一個null,第二個參數是對象的屬性描述符,這個參數是可選的。

 

1.原型是什麼?

首先應該知道我們創建的每一個函數都有一個prototype屬性,這個屬性是一個指向原型對象的指針,這個原型對象的用途是包含由特定類型所有實例共享的屬性和方法。

也就是說,每創建一個函數,就會創建一個對應的原型對象。

一個對象的真正原型是被對象內部的[[Prototype]]屬性(property)所持有。ECMA引入了標准對象原型訪問器Object.getPrototype(object),到目前為止只有Firefox和chrome實現了此訪問器。除了IE,其他的浏覽器支持非標准的訪問器__proto__,如果這兩者都不起作用的,我們需要從對象的構造函數中找到的它原型屬性。 

還是挺抽象,舉個例子吧:

function Person(){
    this.name="大橙子";
    this.age = 26;
    this.sex = "純爺們";
}

var p = new Person();

console.log(p.name);
console.log(p.age);
console.log(p.sex);
console.log(p.career);

Person.prototype.career = "程序員";
console.log(p.career);

輸出結果:
[Web浏覽器] "大橙子"     
[Web浏覽器] "26"     
[Web浏覽器] "純爺們"     
[Web浏覽器] "undefined"     
[Web浏覽器] "程序員"     

上面Person.prototype.career = "程序員";就是通過原型來添加的屬性,所有繼承這個Person的對象,都具有career這個屬性。

這個過程是這樣的,當輸出p.career的時候,首先會在對象p找,因為p對象沒有career這個屬性,這就是為什麼會輸出undefined的原因,然後繼續向上查找,在Person.prototype中找到了career,然後就輸出了“程序員”。 

要了解原型的概念,應該知道_proto_、prototype以及constructor他們之間是什麼聯系

那麼就來分析一下var p = new Person(); 這個過程

上面這個分析圖可以很好的展示,三者的關系,

首先要知道幾個地方,

第一點:就是Empty()函數,這個函數是所有函數的原型,並且他很特殊沒有prototype

第二點:__proto__是內部原型,prototype是構造器原型(構造器其實就是函數,所以上面才說這個是函數對象才有的,而_proto_是每個對象都有的。我的理解它才是構成原型鏈的原因)

①.從中間開始看,首先我創建了一個函數person(),同時JS幫我創建了一個原型對象person.prototype

並把我的person()的prototype指針指向了它,原型對象中有一個constructor屬性,指向了我的person()函數。

②.當我new一個person實例的時候,新創建的實例對象p的_proto_指向了person.prototype

這也是為什麼,我在person.prototype中添加屬性,p也能反映出來的根本原因。

③.person.prototype也是一個對象,那麼他的_proto_是誰呢,如上圖就是Object.prototype,這也不難理解,因為Object是Javascript中所有對象的父級對象,我們創建的所有對象都繼承於此,包括內建對象。同樣因為它也是對象,那麼它也擁有_proto_,圖上表示了它的原型就是null

我們可以打印每一屬性的值來進行確認:

//Person函數的原型對象
console.log(Person.prototype);
//Person原型對象的Constructor
console.log(Person.prototype.constructor);
//判斷實例對象p的原型,是不是Person.prototype
console.log(p.__proto__ === Person.prototype?true:false);
//函數對象Person的_proto_,是不是Empty()
console.log(Person.__proto__);
//Empty()是不是沒有prototype
console.log(Person.__proto__.prototype);
//Empty()的__proto__是不是Object.prototype
console.log(Person.__proto__.__proto__ === Object.prototype?true:false);
//Person.prototype的_proto_是不是Object.prototype
console.log(Person.prototype.__proto__ === Object.prototype?true:false);
//Object.prototype的_proto_是不是null
console.log(Object.prototype.__proto__);

輸出結果:
[Web浏覽器] "[object Object]"    
[Web浏覽器] "function Person(){
    this.name="大橙子";
    this.age = 26;
    this.sex = "純爺們";
}"    
[Web浏覽器] "true"
[Web浏覽器] "function Empty() {}"    
[Web浏覽器] "undefined"    
[Web浏覽器] "true"    
[Web浏覽器] "true"    
[Web浏覽器] "null"    

 

2.原型鏈

上面的原型我們舉的例子沒有特別明顯的顯示這個鏈的過程,看不到具體的繼承關系,所以再分析一個例子

Object.prototype.dead = true;

function animal(){} 
animal.prototype.eat=true;
animal.prototype.sleep=true;
      
      
function bird(){
    this.fly = true; 
}


bird.prototype = new animal();
var a = new animal(); 
var b = new bird();

console.log(a.fly);
console.log(a.eat);
console.log(a.sleep);
console.log(a.dead);
console.log(b.fly);
console.log(b.eat);
console.log(b.sleep);
console.log(b.dead);


測試輸出:
[Web浏覽器] "undefined"     
[Web浏覽器] "true"     
[Web浏覽器] "true" 
[Web浏覽器] "true"     
[Web浏覽器] "true" 
[Web浏覽器] "true"     
[Web浏覽器] "true"     
[Web浏覽器] "true" 

下面我再畫圖分析一下這個

①下圖是在bird.prototype = new animal();之前,創建好函數之後的狀態

 

②繼續執行程序

從上圖就可以明顯看到

實例對象b->bird.prototype->animal.prototype->Object.prototype->null有一個鏈式的繼承關系

也就是為什麼

console.log(b.eat);

console.log(b.sleep);

console.log(b.dead);

會打印出來true的原因了。

 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved