1. 程式人生 > >顯示原型和隱式原型,手繪原型鏈,原型鏈是什麼?為什麼要有原型鏈

顯示原型和隱式原型,手繪原型鏈,原型鏈是什麼?為什麼要有原型鏈

顯式原型:prototype             

 隱式原型:__proto__

1. 每個函式function都有一個prototype,即顯式原型(屬性)
2. 每個例項物件都有一個__proto__,可稱為隱式原型(屬性)

3. 物件的隱式原型的值為其對應建構函式的顯式原型的值

4. 總結:

  * 函式的prototype屬性: 在定義函式時自動新增的, 預設值是一個空Object物件

  * 物件的__proto__屬性: 建立物件時自動新增的, 預設值為建構函式的prototype屬性值

 *Object.prototype的__proto__屬性指向null。

區別:

__proto__是每個物件都有的一個屬性,而prototype是函式才會有(函式也有__proto__)的屬性。
__proto__指向的是當前物件的原型物件,而prototype指向它的建構函式的原型物件。

作用:

1、肯定是為了繼承!2、prototype用來實現基於原型的繼承與屬性的共享。3、__proto__就構成了我們常說的原型鏈訪問構造方法中的顯示原型,同樣用於實現基於原型的繼承。

在js中萬物皆物件,方法(Function)是物件,方法的原型(Function.prototype)是物件,物件具有屬性(__proto__)稱為隱式原型,物件的隱式原型指向構造該物件的建構函式的顯式原型

[javascript] view plain copy
  1. //定義建構函式
  2.   function Fn() {   // 內部語句: this.prototype = {}
  3.   }  
  4.   // 1. 每個函式function都有一個prototype,即顯式原型屬性, 預設指向一個空的Object物件
  5.   console.log(Fn.prototype)  
  6.   // 2. 每個例項物件都有一個__proto__,可稱為隱式原型
  7.   //建立例項物件
  8.   var fn = new Fn()  // 內部語句: this.__proto__ = Fn.prototype
  9.   console.log(fn.__proto__)  
  10.   // 3. 物件的隱式原型的值為其對應建構函式的顯式原型的值
  11.   console.log(Fn.prototype===fn.__proto__) // true
  12.   //給原型新增方法
  13.   Fn.prototype.test = function () {  
  14.     console.log('test()'
    )  
  15.   }  
  16.   //通過例項呼叫原型的方法
  17.   fn.test()
  •     建構函式的顯示原型的隱式原型:
  1. 內建物件(built-in object):比如Array(),Array.prototype.__proto__指向什麼?Array.prototype也是一個物件,物件就是由 Object() 這個建構函式建立的,因此Array.prototype.__proto__ === Object.prototype //true,或者也可以這麼理解,所有的內建物件都是由Object()建立而來。
  • 自定義物件
1. 預設情況下:
function Foo(){}
var foo = new Foo()
Foo.prototype.__proto__ === Object.prototype //true 理由同上
Foo.prototype===foo._proto_ //true
2. 其他情況: 
(1)
 function Bar(){}
//這時我們想讓Foo繼承Bar
Foo.prototype = new Bar()
 Foo.prototype.__proto__ === Bar.prototype //true
(2)
//我們不想讓Foo繼承誰,但是我們要自己重新定義Foo.prototype
複製程式碼
Foo.prototype = {
  a:10,
  b:-10
}
//這種方式就是用了物件字面量的方式來建立一個物件,根據前文所述 
Foo.prototype.__proto__ === Object.prototype
複製程式碼

: 以上兩種情況都等於完全重寫了Foo.prototype,所以Foo.prototype.constructor也跟著改變了,於是乎constructor這個屬性和原來的建構函式Foo()也就切斷了聯絡。

  • 建構函式的隱式原型

既然是建構函式那麼它就是Function()的例項,因此也就指向Function.prototype,比如 Object.__proto__ === Function.prototype

手繪原型鏈


原型鏈是什麼

實現繼承主要依賴原型鏈。 

什麼是原型物件。我們知道每個建構函式一旦建立都有prototype指標指向它的原型物件(建構函式.prototype)。而原型物件(建構函式.prototype)會預設生成一個constructor指標又指向建構函式。在建立例項時,例項有一個內部屬性[[prototype]]指向該原型物件。原型物件內建立的所有方法會被所有例項共享。 

原型是什麼?

在JavaScript中原型是一個prototype物件,用於表示型別之間的關係。

什麼是原型鏈。

JavaScript萬物都是物件,物件和物件之間也有關係,並不是孤立存在的。物件之間的繼承關係,在JavaScript中是通過prototype物件指向父類物件,直到指向Object物件為止,這樣就形成了一個原型指向的鏈條,專業術語稱之為原型鏈。

原型鏈就是建立一個建構函式,它會預設生成一個prototype屬性並指向原型物件。使用下一個建構函式的原型物件作為這個建構函式的例項。即 nextFuction.prototype = new thisFuction(); 

在下下一個建構函式的原型物件 = new nextFuction。這樣下去就會構成一條例項與原型之間的鏈條,這就是原型鏈。

為什麼要有原型鏈

建構函式的所有例項都可以訪問建構函式原型中的方法和屬性。

也就是把共有的東西統一存放到一個共享空間。這樣可以避免相同函式重複宣告,減少空間佔用,節省記憶體。

實現繼承,子類繼承父類的方法和變數;

原型上可以定義一些方法和變數;

以這個原型建立的物件,可以使用原型方法和變數,從而實現繼承。