深刻理解javascript原型和閉包(6)——繼承

爲什麼用「繼承」爲標題,而不用「原型鏈」?javascript

原型鏈若是解釋清楚了很容易理解,不會與經常使用的java/C#產生混淆。而「繼承」確實經常使用面嚮對象語言中最基本的概念,可是java中的繼承與javascript中的繼承又徹底是兩回事兒。所以,這裏把「繼承」着重拿出來,就爲了體現這個不一樣。html

 

javascript中的繼承是經過原型鏈來體現的。先看幾句代碼前端

以上代碼中,f1是Foo函數new出來的對象,f1.a是f1對象的基本屬性,f1.b是怎麼來的呢?——從Foo.prototype得來,由於f1.__proto__指向的是Foo.prototypejava

訪問一個對象的屬性時,先在基本屬性中查找,若是沒有,再沿着__proto__這條鏈向上找,這就是原型鏈web

看圖說話:面試

上圖中,訪問f1.b時,f1的基本屬性中沒有b,因而沿着__proto__找到了Foo.prototype.b。json

 

那麼咱們在實際應用中如何區分一個屬性究竟是基本的仍是從原型中找到的呢?你們可能都知道答案了——hasOwnProperty,特別是在for…in…循環中,必定要注意。閉包

 

等等,不對! f1的這個hasOwnProperty方法是從哪裏來的? f1自己沒有,Foo.prototype中也沒有,哪兒來的?app

好問題。webapp

它是從Object.prototype中來的,請看圖:

對象的原型鏈是沿着__proto__這條線走的,所以在查找f1.hasOwnProperty屬性時,就會順着原型鏈一直查找到Object.prototype。

 

因爲全部的對象的原型鏈都會找到Object.prototype,所以全部的對象都會有Object.prototype的方法。這就是所謂的「繼承」。

固然這只是一個例子,你能夠自定義函數和對象來實現本身的繼承。

 

說一個函數的例子吧。

咱們都知道每一個函數都有call,apply方法,都有length,arguments,caller等屬性。爲何每一個函數都有?這確定是「繼承」的。函數由Function函數建立,所以繼承的Function.prototype中的方法。不信能夠請微軟的Visual Studio老師給咱們驗證一下:

看到了吧,有call、length等這些屬性。

那怎麼還有hasOwnProperty呢?——那是Function.prototype繼承自Object.prototype的方法。有疑問能夠看看上一節將instanceof時候那個大圖,看看Function.prototype.__proto__是否指向Object.prototype。

 

原型、原型鏈,你們都明白了嗎?

---------------------------------------------------------------------------

本文已更新到《深刻理解javascript原型和閉包系列》的目錄,更多內容可參見《深刻理解javascript原型和閉包系列》。

另外,歡迎關注個人微博

學習做者教程:《前端JS高級面試》《前端JS基礎面試題》《React.js模擬大衆點評webapp》《zepto設計與源碼分析》《json2.js源碼解讀

相關文章
相關標籤/搜索