1. 程式人生 > >【JS】從Function說原型

【JS】從Function說原型

前言

最近小組要做學習與交流,本來準備做ES6的使用,組員說先講下JS的原型。琢磨了下,一臉懵,平時在用這個,但是讓我去講,還真不知道怎麼講,趁機再梳理一次。

Function

平時會使用大量的Function,但是真的懂Function嗎?

console.log(typeof Object);
console.log(typeof Function);

上面的輸出是什麼呢?機智的小夥伴已經知道是,對,是function。是不是感覺很奇怪?

JS物件

首先,要明確一點,JS中所有的函式都是Function的例項。要注意的一點是,Function自身能夠生成自身,即Function的原型就是Function。
JS物件包含三種:

  • 本地物件。獨立於宿主環境(瀏覽器)的物件。包括Object、Array、Date、RegExp、Function、Error、Number、String、Boolean。
  • 內建物件:包括Math、Global(window,在js中就是全域性變數),使用的時候不需要new。
  • 宿主物件:包括自定義物件、DOM、BOM。

一張圖

這裡寫圖片描述
在JS中Object、Function既是物件、也是函式。

prototype

prototype表明例項自身的屬性。如上圖中function Foo,Foo.prototype中記錄中Foo自身的原型屬性,其中constructor表明Foo的構造器。

_proto_

_proto_ 表明例項的原型是誰,如上圖示:foo的_proto_指向Foo.prototype。

prototype與_proto_的區別

  • prototype表明例項自身的屬性
  • _proto_表明例項的原型是誰
  • 構造器具有prototype和_proto_,單純例項只具有_proto_

原型鏈

原型鏈就是原型的集合,一級一級向上查詢,直到查詢到null為止。

屬性查詢

  1. 在訪問物件的某個成員的時候會先在物件中找是否存在
  2. 如果當前物件中沒有就在建構函式的原型物件中找
  3. 如果原型物件中沒有找到就到原型物件的原型上找
  4. 知道Object的原型物件的原型是null為止

比如我們想要查詢例項foo原型上的屬性,首先先找它的原型屬性foo._proto_,即Foo.prototype。接著繼續向上查詢Foo.prototype._proto_,即Object.prototype。繼續向上Object.prototype._proto_,找到了null。查詢結束。

原型繼承

需要注意的是原型繼承與類繼承是不同的概念。下面看一個demo:

Function.prototype.hh = 123;
function Foo(){}
let foo = new Foo();
console.log(Foo.hh)
console.log(foo.hh)

輸出是:

123
undefined

你思考的結果是否是和實際輸出一樣呢?

按照我們面向物件的思維,Foo是Function的例項,foo是Foo的例項,foo應當是應該繼承Function的屬性和Foo的屬性的,但是很顯然,並不是。這是類繼承和原型繼承很大的不同所在。

原因還是要從上面的那張圖說起,此時foo的原型鏈應該是Foo.prototype + Object.prototype + null,和Function.prototype並沒有什麼關係。這一點是需要特別注意的。

如果能搞懂這一點,那麼原型繼承也就懂,demo就不寫了,網上一堆。

原型鏈上的元素

原型鏈上的元素都是物件,原型鏈必須是有限長度,且原型鏈以null為終結,那麼其它位置上都是些什麼呢。

倒數第一位

null,無可否認。

倒數第二位

從實現上來看,倒數第二位與倒數第一位都是唯一的。因為原型鏈上所有的元素都是物件,所以倒數第二個元素應該是所有物件的基礎物件。即Object.prototype。

倒數第三位

那麼倒數第三個元素是不是固定的呢?不是。從倒數第二個元素是Object.prototype來看,通過{}字面量和new Object()建立的物件都在倒數第三這個位置。另外還有兩個特例,一個是除內建函式之外的內建物件,如Math、JSON;一個是除Object之外的內建函式的prototype屬性指向的物件,如Function.prototype。即Math、JSON、(Function、Array、String、Boolean、Number、Date、RegExp、Error).prototype。

倒數第四位

所有除Object之外的內建函式作為構造器呼叫時生成的例項物件都在倒數第四位。即Object、Function、Array、String、Boolean、Number、Date、RegExp、Error。

參考