JavaScript的原型與原型鏈

在講原型之前,我們先說說js的數據類型,有一下幾種

原始數據類型:String、Number、Boolean、Null、undefined、Symbol(ES6)、BigInt(ES10) 

引用類型:Object

JS 中 typeof 輸出分別是什麼呢?

  1)基礎數據類型

typeof 'a' // 'string'
 
typeof 12  // 'number'

typeof false // 'boolean'

typeof null  // 'object'

typeof NaN  // 'number'

 2)引用數據類型

typeof Object   //'function' 

typeof Number   //'function'
 
typeof String   //'function'

typeof Boolean  //'function'

typeof Function //'function'

這個時候有人肯定會有疑問,爲啥引用類型這裏輸出的function,我們知道任何幾個結果的輸出都是有原因的,我們先在這裏埋下一個伏筆。接下來我們進入主題,講講原型

一、構造函數創建對象

我們先使用構造函數創建一個對象

function Person (name, age) {

      this.name = name
      this.age = age
}

var person = new Person('zbq', 28)

我們創建了一個Person構造函數,然後通過new來創建來一個實例person,接下來我們開始進入主題

prototype屬性

每個函數都有一個prototype屬性,指向實例原型,構造函數與實例原型的關係如下圖所示:

__proto__屬性

每個對象都有一個__proto__屬性,指向實例原型,該實例與實例原型的關係如下入所示

 

因此person的__proto__屬性與Person構造函數的prototype的屬性指向的是同一個實例原型 Person.prototype,我們來驗證一下

person.__proto__ === Person.prototype // true

補充說明:絕大部分瀏覽器都支持這個非標準的方法訪問原型,然而它並不存在於 Person.prototype 中,實際上,它是來自於 Object.prototype ,與其說是一個屬性,不如說是一個 getter/setter,當使用 obj.__proto__ 時,可以理解成返回了 Object.getPrototypeOf(obj)。

 

constructor屬性

我剛說了構造函數與實例原型的關聯,以及實例與實例原型的關聯,那實例原型與構造函數有啥關聯呢?這就是我們接下來要說的

實例原型的constructor屬性,它是指向構造函數的,我們用代碼驗證一下

Person.prototype.constructor === Person //true

它的關係圖如下所示:

接下來有人肯定要問了,那Person.prototype它有指向的是誰呢?這就是我們接下來要講的原型與原型之前的關聯了

 

二、原型與原型

前面我們說過每個對象都有一個__proto__屬性,而實例原型也不例外,它也有一個__proto__指向上一個實例原型對象,因此就有如下的Person.prototype.__proto__指向Object.prototype。

三、原型鏈

原型與原型之間通過__proto__建立的的關聯就是原型鏈(下圖的藍色線條),這裏再補充一下Object.prototype指向的原型是null

我們可以用代碼驗證一下

Person.prototype.__proto__ === Object.prototype // true

Object.prototype.__proto__ === null             // true

 

四、拓展

我們先記住一個知識點,instanceof 它表示是一種繼承關係。然後我們再看看以下的一個例子

Object instanceof Function    // true

Function instanceof Object    // true

Function instanceof Function  // true 

肯定很多人一臉的疑惑,在想爲什麼?疑惑是正常的。不過我們先來一步步分析吧!

1、首先我們先看一個函數的創建

// 方式一:傳統方式來新建一個函數
function add1 (a, b) {

   return a + b

}
// 方式二:通過new的方式來創建(平時不推薦使用)
var add2 = new Function ('a', 'b', 'return a + b')

根據此可以得出一個結論:

1) 函數也是對象,所以也有__prototype__屬性

2) Function是一個構造函數  function Function () {....}

關係圖如下:

2、創建對象

// 方式一:對象字面量的形式
var obj1 = {}

// 方式二:new方式來創建
var obj2 = new Object()

obj1.__proto__ === Object.prototype // true

obj2.__proto__ === Object.prototype // true

根據以上可以得出一個結論:

1)  對象字面量的創建方式只是new方式的一種快捷創建方式

2) Object也是一個構造函數  function Object () {...}

3) Object也是Function的一個實例 

Object.__proto__  === Function.prototype  // true

以上實例的關係圖如下:

 

所以你現在是不是能懂的爲啥以下的例子的結果都是返回true,以及開篇文章中 typeof Object === 'function'

Object instanceof Function    // true

Function instanceof Object    // true

Function instanceof Function  // true

小結:

1、每個函數都有一個prototype屬性

2、每個對象都有一個__proto__屬性

3、任何函數皆對象

 

以上文章是參考至:

https://segmentfault.com/a/1190000008959943

https://www.cnblogs.com/wangfupeng1988/tag/%E5%8E%9F%E5%9E%8B

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