翻閱到之前的學習筆記,加上本身如今的理解,談一談JS的原型鏈。程序員
tips:本文有不少胡言亂語,若是你已經掌握js原型鏈,不建議閱讀本文,以避免被我誤導。編程
function Person() {
}
let person = new Person();
複製代碼
當初我很不理解,person的原型是什麼? 不少教程就說:數組
person的原型是 person.__proto__bash
我又疑問,那Object的原型呢?編程語言
Object.__proto__函數
當初我真是特別崩潰。就好像,我問:老王的兒子是誰?有人回答:老王的兒子是老王.兒子
學習
我指望的回答是相似於小李,小張的答案,而不是老王的兒子是老王.兒子
這種間接的答案。ui
咱們知道其餘編程語言中的面對對象,每每都是基於類的面對對象。this
就好像:有人類的概念,而後咱們能夠建立一我的類的實例。spa
基於類的面對對象的代碼可能長這樣子:
class Human{
}
new p1 = new Human()
複製代碼
而後中國人的概念繼承自人類
class Chinese extend Human{
}
let c1 = new Chinese()
複製代碼
JS和基於類的繼承不一樣,JS是基於原型的。
可是在原型繼承中,就沒有人類,中國人類的概念了,取而代之的是一我的,一箇中國人的概念。
漢語中,咱們會說:李華是一我的。
一我的的概念和奇特。 你能夠說小明是小明,小明是人類,可是很差說小明是「一我的」 就好像英文中,"a person" "the person" 的概念,當咱們跟說道小明的時候,咱們可能再說 "the person" 而不是 "a person",你找不到"a person" 由於你找到它的時候,他就是"the person"了。
JS中,除了四種基本類型,其餘一切都是對象。在js中函數也被定義爲對象。那是JS對象就要有原型,lihua
的原型是什麼?你可能會這樣作:
lihua.__proto__
,但其實否則,對象的原型是抽象的概念,他不存在於實體(js解釋器的內存中)。
lihua
是什麼? lihua
是 一我的
,一我的
具備的特徵李華都應該有。地球上有許多人,可是並不存在一我的
這樣的實體。
有人可能會說:"我不是在控制檯打印了lihua.__proto__
嗎,那麼在js解釋器的內存中,lihua
的 __proto__
指向的內存不就是一我的
嗎?"
其實這是一種誤解,lihua
並無一個叫__proto__
的屬性。
lihua
的原型的特徵是什麼,可是不能說
lihua
的原型在某塊JS內存區。
在我我的理解中,用一個
的概念更容易理解JS的原型鏈.Object.prototype
能夠理解爲一個對象。Function.prototype
能夠理解爲一個函數,而後一個函數的原型就是一個對象,因此 Function.prototype.__proto__ === Object.prototype
下面是我畫的原型鏈的圖
obj
就是Object.prototype
、一個對象
;fun
就是Function.prototype
、一個函數
;以此類推。
咱們來捋一捋原型鏈。lihua
原型是一我的
,一我的
的原型是一個對象
。 Array
是一個函數
,因此他的原型是一個函數
,同時他又是Functin
的實例。一個Array的實例又是一個數組
,一個數組
的原型又是一個對象
。
用一個
的概念來理解原型,是否是容易不少?
咱們知道,除了經過構造函數,咱們還能夠經過Object.create()來建立一個對象。
let a = {}
let b = Object.create(a)
複製代碼
這段代碼的意思就是建立一個對象b,並將b的原型指定爲a。
這是有人可能會說:我這不是找到b的原型了嗎?
b.__proto__ === a //true
其實我是這樣想的:
let obj = {
name:"lihua"
}
let str = JSON.stringfiy(obj)
複製代碼
若是把obj,str理解爲JSON數據,他們表達的信息沒有任何區別。
上述代碼中,a既是JS解釋器內存中的對象,又能表達b的原型有怎樣的特徵。 語法上b.__proto__ === a //true
,可是邏輯上b的原型是抽象的概念,a只是b的原型的一種表達。
好比下面三段代碼
function hi(){
console.log("hi")
}
let h1 = new hi()
let lihua = {
name:"lihua"
}
let l1 = Object.create(lihua)
let aperson = {
eat:()=>{
console.log(this.name + " is eatting")
}
}
let lihuai = Object.create(aperson)
複製代碼
第一段代碼和第二段代碼沒有任何語法錯誤,可是邏輯上沒人會這麼寫,由於h1
,l1
沒有任何邏輯上的意義。
第三段代碼和第二段沒有什麼語法上的區別,可是他有邏輯意義。咱們建立了一個對象lihua
,lihua
的原型是一我的,而一我的有eat
這個固有特徵,你們都知道這是什麼意義。等價於下面的代碼:
function Person(){}
Person.prototype.eat = ()=>{
console.log(this.name + " is eatting")
}
複製代碼
說了半天,就是想表達:不要單純從語法上理解JS的原型鏈,還要考慮其中的邏輯意義。對象和對象的原型之間的關係就想李華和一我的之間的關係。