1. 程式人生 > >js奧義:原型與原型鏈(1)

js奧義:原型與原型鏈(1)

要弄懂原型鏈,首先應先明白prototype原型物件、__proto__、物件三者之間的關係。

引入建構函式的相關定義:

  建構函式是一種比較特殊的函式,用於批量例項化物件。通俗一點說,建構函式是用於生成物件的模板。

由於工廠模式在例項化物件時會存在同一功能程式碼在記憶體中開闢不同記憶體空間從而造成記憶體空間浪費的問題,更多的人選擇使用建構函式來例項化物件,es6中引進的class關鍵字正是基於建構函式的思想

建構函式的本質上是將物件中一些公共的方法和屬性 抽取出來,然後將這個函式封裝成可複用的建構函式.

 建構函式的特點(與工廠函式相比較):    

    a. 函式名首字母大寫;

    b.  函式體內沒有關鍵字new,在例項化一個物件時會使用關鍵字new;

    c.  建構函式體內的this指代當前例項化物件;

    d.   函式體內沒有關鍵字return。

 function Fn() {
            this.n = 20
        }
        Fn.prototype.say= function() {
            console.log(this.n)
        }
        var deb = new Fn()

  

 建構函式的new關鍵字在例項化物件時會做以下四件事:

  a.現在記憶體中開闢一塊記憶體空間(new obj);

  b.讓建構函式體內的this指向這個物件   (因而,this指代當前物件);

  c.將建構函式體內的屬性和方法賦值給這個這個物件;

  d.返回這個物件 (因而,建構函式體內沒有return關鍵字)

為了區別對待,以下將建構函式稱為父類,將例項化物件稱為子類。

一:原型

  1.定義

 每一個函式身上都有一個prototype(原型),由於這個prototype的值是一個物件型別,因而又叫做原型物件,ptototype屬性是函式獨有的屬性!

  2.原型的作用

  原型物件的作用通常用來共享父類的方法,由於方法是函式,本質上也是一個物件,而物件的記憶體地址儲存在堆空間裡,如同工廠模式一般,多個記憶體空間存放相同的程式碼,會造成大量空間被佔用,因而將公有的方法新增在父類

的prototype上,也就是寫入了同一物件上,呼叫的時候也就避免了多個空間存放同一程式碼的錯誤示範,而由於父類的屬性的值是基本型別,所佔記憶體較少,所以我們往往將其新增到父類函式體的內部。

  function Fn() {
            this.n = 20
        }
        Fn.prototype.sing = function() {
            console.log(this.n)
        }
        var deb = new Fn()
        var deb2 = new Fn()
        console.log(deb.sing === deb2.sing) //true

 二:__proto__

  與函式的prototype屬性不同,每一個obj的物件都有一個__ptoto__屬性,這個__proto__屬性隱式的指向了這個子類的的建構函式的prototype屬性!但是這個__proto__屬性是不可見的,這也就是為什麼將其稱作是隱式的,不過好在瀏覽器的支援下,它被定義為__proto__

  如果看到這裡,希望你再好好思考一下 ”萬物皆物件“這句話的含義

  從父類的角度看,子類的_proto_屬性隱式指向了它的父類的prototype屬性;從子類的角度看,子類自身的__proto__屬性指向了它的父類的prototype屬性

  假如我們對比父類的prototype與子類的__proto__屬性:

        console.log(Fn.prototype === deb.__proto__)//true

  理解了這一點,就可以明白為什麼建構函式新增在其原型物件上的方法,例項化物件可以共享使用了:因為建構函式的prototype屬性指向的 與 例項化物件的__proto__屬性指向的 是同一個物件,也就是父類的prototype物件!


這樣,就具備了深入理解原型鏈的條