Object,Array,Number,String,普通函數,普通對象,Function等的原型鏈關係——多次面試失敗總結的經驗

以前說到原型鏈就只知道通過原型鏈繼承,構造函數和它的實例之間的原型鏈的關係啊這些東西,最近面試被問得很懵,後來看到一篇文章總結的特別好,當時看明白了,後來面試又忘了一部分,所以今天打算自己總結一下,加深印象。

JS中沒有類的概念,萬物皆是對象

其他語言中的繼承於類,在JS中是 對象繼承於對象。所以萬物都有__proto__屬性,但是prototype屬性卻不是所有對象都有,只有構造函數纔有。
例如 使用instanceof用來測試變量是不是Object類型,除了基本數據類型外,其他的比如函數、數組、鍵值對對象以及比較特殊的幾個構造函數——Number、Array、String、Boolean、Function等,用instanceof Object結果都是true

  1. instanceof的原理是通過原型鏈一直查找,找到相同的原型就會返回true
  2. 在我們平時使用構造函數實例化對象的過程中,我們知道對象有一個屬性叫__proto__,這個屬性是指向它的構造函數的原型prototype

面試中被問到typeof Object返回什麼?
這個回答上來了,是function,因爲Object是對象的構造函數,它是Function的實例,實際上所有的構造函數例如Array、Number都是Function的實例。下面我們通過代碼使用上面兩條測試來證明:

Object instanceof Function // true
Array instanceof Function //true
Object.__proto__ === Function.prototype // true
Number.__proto__ === Function.prototype // true

所以說Number、Array、String、Boolean這些構造函數都是Function的實例,那麼Function也是構造函數,那麼Function是不是 Function 自身的實例呢?
答案是:是的。

Function instanceof Function // true
Function.__proto__ === Function.prototype // true

如上所示,這就是神奇的地方所在了,Function的對象屬性__proto__指向了它自己的原型prototype
到這裏我們可以得出幾個結論:

  • 任何對象都有__proto__屬性,但是隻有函數纔有prototype屬性
  • 同一個對象的__proto__屬性和prototype屬性是沒有關聯的,除了Function
  • 對象的__proto__屬性是用來和其父“類”關聯的,構造函數的prototype是用來和其實例關聯的,所以對於同時存在這兩個屬性的構造函數來說,這兩個屬性之間是沒有什麼關係的,也就對應上一條。
  • 任何構造函數都是Function的實例,任何對象都是Object的實例
  • 任何對象直接調用方法,例如obj.foo(),在實例本身沒有這個屬性的情況下,都是從其__proto__屬性上查找的,也就是從該對象的構造函數的prototype屬性上查找。

這裏有一道典型的題目就是考對上面幾條的理解,我們都知道Object.prototype.toString方法可以用來判斷數據類型,那麼用Object.toString可以嗎。
答案是:不可以。
因爲Object.toStringObject.__proto__.toString,也就是Function.prototype.toString,和Object.prototype.toString根本不是同一個函數。

下面我們通過一張圖來描述JS中的原型鏈。

JS中的原型鏈

在這裏插入圖片描述
OK,這就是JS中的原型鏈的樣子,都是圍繞前面提到的幾點進行繪製的。

參考鏈接

附上之前看的文章的鏈接:再談javascriptjs原型與原型鏈及繼承相關問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章