JS 原型的解釋

首先明確兩個概念: 構造函數和 instance 分別是什麼瀏覽器

  • 構造函數
    JS 中並無在語法層面上面區分構造函數和普通函數, 惟一的區別是調用方式
    使用 new 調用的函數就是構造函數, 沒有則是普通函數.函數

  • 實例
    new Constructor() 返回的對象稱爲 Constructor 的一個實例prototype

而後提出一個規則:
在構造函數的原型上面附加的屬性或者方法, 能夠被其全部的實例共用.code

能夠推導出:對象

  • 構造函數能夠訪問到它的原型, 而且向其上面添加方法和屬性原型鏈

  • 構造函數的原型應該是一個對象, 這樣才能向其上添加方法和屬性原型

  • 實例也擁有其構造函數的原型的一個引用, 要否則沒法共用.io

解釋:
1 構造函數的確有一個屬性, 能夠訪問到它的原型, 屬性名爲 prototype.
規範下稱呼:
a 函數的 prototype 屬性, 稱爲 '原型屬性'
b 函數的 原型屬性指向的 對象, 稱爲 '原型對象'function

2 實例也的確擁有一個對其構造函數的原型的引用
這個引用是一個內部屬性, 使用 [[prototype]] 表示, 稱爲 '實例的內部屬性 prototype'
a 內部屬性意味着這個玩意不可讀, 你沒有辦法訪問到的
b 部分瀏覽器爲實例提供了一個屬性 '__proto__', 一樣指向 實例的構造函數的原型對象.構造函數

從實例的角度來看:
1 實例但願知道本身的構造函數是誰
2 實例但願知道本身可使用的方法到底有多少, 但願知道它的構造函數的原型裏面到底有多少方法和屬性

  • 實例何從知道本身的構造函數是誰

    經過 constructor 屬性

每個 instance, 能夠經過 constructor 屬性, 訪問到它的構造函數

instance 並不擁有 constructor 屬性
      當訪問 instance.constructor 的時候
           instance 自己不持有
           從它構造函數的原型對象中查找
           發現存在 constructor 屬性
                返回 constructor 的值.

而且存在有:

構造函數原型對象的 constructor 屬性 始終指向構造函數自己。
 fn.prototype.constructor === fn;
  • 實例想要知道它的構造函數的原型對象擁有多少方法和屬性

    根據上面的 constructor 屬性, 能夠獲得
     instance.constructor.prototype 便可訪問
     或者
     __proto__

應用到具體的場景裏面, JS 的全部數據類型的構造函數是誰, 它們的構造函數的原型對象是什麼樣子的

原始值類型有:

String
Number
Null
Undefined
Boolean

構造函數分別有:

(1).__proto__ // Number
'a'.__proto__ // String
true.__proto__ // Boolean

引用值類型
Array
Function
Object

構造函數分別有:
[].__proto__ // Array
{}.__proto__ // Object
(function (){}).__proto__ // Function

更近一步的思考:
構造函數是否擁有構造函數
構造函數的原型對象是否擁有構造函數

根據上面的信息, 能夠嘗試一下

'a'.constructor.constructor

最終發現:
不論原始值類型, 仍是引用類型, 它們的構造函數的構造函數, 都是 Function
更近一步, Function 的構造函數是誰
通過驗證, Function 的構造函數是它自己.

Function.constructor = Function;

說明構造函數到這裏到底了.

  • 構造函數的原型對象是否擁有構造函數

    擁有, 你糊了, 原型對象自己就擁有一個 constructor 屬性, 指向構造函數自己.

補充:
下面說的是一個規則, 不是一個推導

原型對象自己一樣擁有一個內部屬性 [[prototype]], 指向當前構造函數的構造函數的原型對象.
 這種由原型對象構建而成的鏈表, 就是原型鏈.
 原型鏈存在的意義, 在於儘量的共用方法和屬性. 或者其餘更多的我不知道的意義.

原型鏈長什麼樣子

'hello'

它的原型鏈條的
第一個原型對象

'hello'.constructor.prototype  // = String.prototype

第二個原型對象

'hello'.constructor.prototype.__proto__  // = Object.prototype

這裏不能再用

'hello'.constructor.prototype.constructor.prototype 
 來間接訪問原型對象的構造函數的原型對象了.

說明 constructor.prototype 這個玩意並不靠譜, 在碰見原型對象的時候就很差用了。

第三個原型對象

'hello'.constructor.prototype.__proto__.__proto__  == null;

說明到底了.

相關文章
相關標籤/搜索