JS中的原型鏈和原型的認識

這篇文章主要是學習一下JavaScript中的難點------原型和原型鏈

自定義一個對象

咱們學習一門編程語言,必然要使用它完成一些特定的功能,而面向對象的語言由於符合人類的認知規律,在這方面作得很好,今天我以JS爲例,探索一下JS不一樣於其餘面向對象的語言的地方-------原型和原型鏈javascript

  • 首先,假設你在作一個項目,要造一個新的對象,標準庫裏面沒有。那你只能用構造函數去構造一個
function Person(){
  //構造函數
}

以上Person就是一個構造函數,能夠用來生成小明 小紅 等等人類的實例。java

var person = new Person() //構造出一個對象
person.name = 'xiaoming'
console.log(person.name) // 'xiaoming'

那原型在哪呢,認識原型先認識一下prototype屬性git

prototype

先看一段代碼github

Person.prototype.name = 'god'
var person2 = new Person()
console.log(person2.name) //person2的名字是啥呢???

從上面三行代碼,猜一猜person2的名字是啥,沒錯,就是god面試

person2沒有本身規定名字,可是Person構造函數的prototype上綁定了name,因此由Person構造函數構造的實例對象都默認有一個god的名字。編程

  • 並且這個prototype屬性只存在構造函數上,也就是說prototype是構造函數的屬性!!!
  • 那這個prototype指向了哪裏,那個地方就是--------調用構造函數而生成的對象實例的原型,存的是這個原型的地址。

構造函數和原型的關係

以上就是構造函數和原型之間的關係,構造函數內部的prototype屬性指向了實例對象原型的地址。數組

  • 原型裏面存的是全部實例化對象的共有屬性,好比這個例子的name

Person實例原型的內容

上面紅框是Person實例的原型,若是不直觀的話,下面直接看Array實例的原型瀏覽器

Array實例的原型

紅框的都是你們熟悉的數組的方法吧,他們都放在數組的共有屬性裏面。編程語言


上面的兩幅原型圖裏面,咱們居然發現有共同點,都有一個熟悉 constructor 屬性,待會研究一下這個屬性。函數


如今,咱們已經知道了構造函數和原型的關係了,那person person2這些實例對象和原型有啥關係呢

__proto__屬性

每個構造的實例對象,內部有一個__proto__屬性,它指向了實例原型,存的是原型的地址。

person.__proto__ === Person.prototype 
true
  • __proto__是對象的屬性,並且是瀏覽器強逼着ECMAScript加上的這個規範。

person

以上是構造函數、實例、實例原型之間的關係,不過方向是單向的,哪能不能讓它循環起來呢,原型可不能夠指向構造函數或者實例呢?

constructor

  • 還記得上面咱們發現的那個 不一樣的原型 都有的一個共同的屬性 constructor嘛

構造函數、實例、實例原型之間的關係的方向能夠循環的關鍵就在這裏了。咱們一直叫構造函數,構造函數的,爲何這麼叫呢,對,就是這個原型裏面的constructor屬性。

  • 不過原型是沒法指向實例的,只能夠經過constructor屬性指向 構造函數
Person === Person.prototype.constructor
true

construcor屬性

上面就是經典的鐵三角了。

由以上知識得出一個小公式

對象.__proto__ === 構造函數.prototype

而Person這個構造函數也是對象,那麼

Person.__proto__ === ???

上面的問號填啥呢,咱們按公式填空,應該是構造函數.prototype,Person構造函數的構造函數是誰呢?沒錯,就是Function

Person.__proto__ === Function.prototype
true

在控制檯驗證確實如此。

因此有些之前的疑惑也解開了

Array.__proto__ === Function.prototype
true
String.__proto__ === Function.prototype
true
  • 那問題又來了,構造函數.prototype也是對象啊,它指向誰
  • 既然是對象,那麼裏面就有__proto__屬性
Person.prototype.__proto__ === ???

問號填什麼呢,原型是由誰構造的呢,咱們想到了全部對象的根----------Object

原型的原型

在控制檯驗證以下

Person.prototype.__proto__ === Object.prototype
true
Array.prototype.__proto__ === Object.prototype
true
String.prototype.__proto__ === Object.prototype
true

既然引出了Object,咱們來看一下全部對象的祖宗的原型吧

Object.prototype.__proto__ === null
true

原型的原型

特殊的Function

前面咱們看到了Function構造方法構造除了全部的函數,包括普通的構造函數。

那麼他自身也是一個函數,因此也是由Function構造函數構造的。因此由總結的公式能夠知道

Function.__proto__ === Function.prototype

並且,下面這個很重要,易錯

Function.prototype === Object.__proto__ //哈哈,這個老彆扭了吧,還給你倒過來寫,很容易錯的

解釋:Object也是構造函數啊,屬於對象。Object構造函數也是由Function把它構造出來的,因此是結果是true

最終的關係圖

完整的總結

  • 當你new一個構造函數的時候,建立一個函數實例,那麼 『 函數實例.__proto__ === 該構造函數.prototype
  • 全部的函數都是由Function構造出來的,那麼 『被構造出來的其餘函數.__proto__ === Function.prototype
  • 全部的構造函數的原型對象都是由Object構造出來的,那麼 『全部的構造函數.prototype.__proto__ === Object.prototype

instanceof運算符的實質

首先這有幾個題

Object instanceof Function
Function instanceof Object
Function instanceof Function
Object instanceof Object
  • 能不假思索的說出來嗎,大聲告訴我,答案是什麼。
  • 沒錯,全是true

雖然 instanceof運算符算是咱們的老朋友了,不過背後是咋判斷的呢

規範是這麼寫的

object instanceof constructor

參數

  • object

    要檢測的對象.

  • constructor

    某個構造函數

    instanceof 運算符用來檢測 constructor.prototype 是否存在於參數 object 的原型鏈上

  • 對於 Object instanceof FunctionObject.__proto__ === Function.prototypetrue,解決
  • 對於Function instanceof ObjectFunction.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototypetrue,解決。
  • 對於 Function instanceof FunctionFunction.__proto__ === Function.prototypetrue,解決
  • 對於Object instanceof Object , Object.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototypetrue,解決

只要上面的推導,任一環節你寫錯或者壓根寫不出來(在今天以前我也是瞎搞,運氣好了蒙對了),說明你就不是真懂原型鏈,面試問到稍微變形的題仍是易錯。


  • 在上面的各類原型的變換中,其實難點就在於Function Object 構造函數也是對象 原型對象等全部對象都由Object構造

這四個點。

  • 並且看待問題的角度不一樣,對事實的認知影響很大。好比 Object Function 你把它們當作構造函數或者對象,結果不一樣的。不一樣的場合,換不一樣的角度去認識它們,事物具備兩面性。大概就是背了多年的同一性,巴拉巴拉一堆的哲學原理吧。
  • 各類原型的分析過程,讓我回憶起了,被數學支配的恐懼。邏輯必須合理、一步是一步、抽絲剝繭看本質,大概是這麼多年應試教育留在腦子裏面的深深烙印吧。
  • JS愈來愈有意思了,感受應該快入門了。

原型鏈

  • 咦,在哪呢。
  • 原型鏈就在上面啊。每一個對象,沿着__prto__屬性有一條鏈子,找呀找呀,一直找到Object.prototype爲止
感謝 冴羽大神和若愚大神的 文章
相關文章
相關標籤/搜索