Jascript原型鏈以及Object和Function之間的關係

  • 2019 年 10 月 4 日
  • 筆記

先看一個簡單的function變量

function fun1(name) {  this.name = name;  }    console.log("fun1", fun1)

從結果可以看到定義一個function,它裡邊所含有的內容這六個屬性是每個function所必有的,直接看第五個prototype(注意prototype是一個對象)就是傳說中的原型(本文只稱它為prototype,也叫顯性原型),第六個屬性是灰色的並且用尖括號括起來,在以前版本的瀏覽器它有另外一個名字叫__proto__(也叫隱形原型)。

如果大家去實驗一下就會發現,每個對象都會有__proto__這個屬性,但一般情況下只有聲明function的變量(例如上圖中的fun1)才會有(自動生成)prototype這個屬性,所以總結一下是對象只有隱形原型,而function既有隱形原型(_proto_)又有顯性原型(prototype),因為函數在js裏面既是函數也是對象。

可以看到在 prototype里有兩個屬性constructor和__proto__,在前面我們說過prototype是一個對象和每個對象都會有__proto__這個屬性,因此prototype也是有__proto__這個屬性;constructor(構造方法)這個屬性是在生成prototype時自動生成的屬性,其指向函數本身(在申明函數時,js自動創建該函數的peototype屬性)。

function fun1(name) {  this.name = name;  }    var temp = new fun1("");  var obj = new Object;  console.log(temp.__proto__ === fun1.prototype)//true  console.log(fun1.__proto__===Function.prototype)//true  console.log(obj.__proto__ === Object.prototype)//true   

總結一下:

所有對象都有__proto__屬性,是用來通過__proto__找到它的原型即prototype,function聲明的變量的__proto__指向Function的prototype,其它對象的__proto__指向Object的prototype function聲明的變量、Function和Object都有prototype, 有prototype的東西可以產生實例(即可以作為new 後邊的值)。 prototype它是一個對象(在聲明函數變量是在函數內部由js自動創建),因此它也有__proto__,並且指向Object的prototype。

Function和Object非常特殊,我們來具體分析

首先看一下Function里的東西

console.log("Function", Function);  console.log("Function.__proto__", Function.__proto__)

從控制台的打印可以明顯的看出Function的__proto__指向了它自己的prototype

接下里看Object(Object里有很多其它的東西,為了簡潔我直接打印Object的prototype)

console.log("Object.prototype", Object.prototype)  console.log("Object.__proto__", Object.__proto__)

Object的prototype和Function的prototype的__proro__指向是相同的如下圖:

綜上可以看出Object的__proto__指向Function的prototype,而Object的prototype並沒有灰色的<prototype>即__proto__,即它是一切之源。

console.log("Object.prototype.__proto__", Object.prototype.__proto__)

我將Object的prototype稱為源型,下面我給出我個人對這些現象的解釋:

源型是js的內置的一段代碼,所有所有通過這個源型創造出的都是object,第一步先創造出Function的prototype,因此這個prototype的__proto__指向源型,然後再通過這個prototype造出Function,因此Function的__proto__指向它自己的prototype,然後用Function造出Object,因此Object的__proto__指向Function的prototype,然後js直接將Object的prototype替換為源型。

並且我認為js里判斷繼承(即A instanceof B)是沿着__proto__往下走,首先要求B必須有prototype屬性且必須是一個對象(否則會瀏覽器會報 'prototype' property of B is not an object),判斷時先判斷A的__proto__是否和B的prototype指向是否相同(即===結果為true),若相同則返回true,若不相同則判斷A的__proto__指向屬性里是否還有__proto__屬性,若有則進行再次進行判斷指向是否相同,直到找到源型,它的__protot__為null,返回false

為了證明只要A的__protot__和B的prototype指向相同就返回true,給了如下測試:

var obj = new Object;  function fun () {};  console.log(obj instanceof fun);  var temp = new Object  fun.prototype = temp  obj.__proto__ = temp;  console.log(obj instanceof fun)

有點顛覆三觀不過習慣就好。

下面用我的結論來解釋下邊四個現象:

console.log(Function instanceof Function)  console.log(Function instanceof Object)  console.log(Object instanceof Function)  console.log(Object instanceof Object)

Function的__proto__和Function的prototype指向相同,因此返回true, Function的__proto__和Function的prototype指向指向相同,Function的prototype的__protot__和Object的prototype指向相同,因此返回true。 Object的__proto__和Function的prototype指向相同(因為Object就是以Function為模板創造的),因此返回true。 Object的__proto__指向Function的prototype,Function的prototype的__proto__指向Object的prototype,這個prototype是屬於Object(饒了一圈),因此返回true。 只要高清內部原理,理解instanceof就非常簡單

下面再來一個小測試:

var obj = new Object;  obj.__proto__ = Function.prototype;  console.log(obj instanceof Function)//true

總結:prototype是原型,__proto__所指向的以及其後的所有prototype稱為原型鏈。「js里一切皆對象」倒不如所是js里的所有對象都是由「源型」生成。

原文:https://blog.csdn.net/backee/article/details/83378772