你是否理解js的Object與Function與原型鏈

js中,Function的本質是什麼?
Object的本質又是什麼?
js中有幾條原型鏈?javascript

clipboard.png

javascript的語言基於原型鏈,而實際上js的有兩條原型鏈。開發者主要用到的是圖中的紅色原型鏈,如給Array.prototype.xxx=yyy,那麼就能夠[...].xxx,數組實例對象就繼承了其構造函數原型對象中的數據,固然實踐通常不會給修改Array這類構造函數的原型對象,最多的就是自定義構造函數,而後給自定義的構造函數定義原型對象,那麼這個構造函數的全部實例對象也就都繼承了原型對象中的數據。這就是圖中紅色原型鏈的所表示的。java

那麼Array.prototype和自定義構造函數function f(){}的prototype的原型對象是從哪裏來的,是誰創造了它?數組

諸如Array.prototype.xxx=yyy,這實際上就是引用了Array的原型對象prototype而已,也就是它的原型對象就已經存在了,而後才讓其可以被引用到。app

包括Array.prototype,仍是String.prototype,仍是Object.prototype,仍是Function.prototype,仍是自定義構造函數function f(){}的prototype,它們都不是開發者建立的,而是Function構造函數在建立其餘構造函數時,用Object()建立的。函數

能夠說Function構造函數是javascript世界中的萬物之主,像盤古開天闢地建立了javascript的語言世界和運行機制。而OBject的本質就是用於建立原型對象。this

Function構造函數內部有一個this.prototype=new Object(),當Function造物時,就同時經過這句this.prototype=new Object(),給這個物賦予了靈魂。而Object在javascript中的本質也就在於此,做爲Function手中的魂燈,賦予其建立的物體靈魂,也就是給予它原型對象,讓它可以經過原型對象,可以從上面繼承和吸取能量。spa

Function構造函數,建立了Array構造函數,同時經過new Object()給其建立了prototype對象,所以有Array.prototype。而後[1,2,3]就是由Array構造函數建立,所以[1,2,3]數組實例對象,繼承了Array構造函數中的數據,同時繼承了Array.prototype中的數據。prototype

Array.prototype原型對象是由this.prototyoe=new Object()建立的,所以Array.prototype原型對象的構造函數是Object構造函數(也能夠是稱爲對象),Array.prototype原型對象也就繼承了其生父Object構造函數中的數據,也同時繼承了Object.prototype原型對象的數據。對象

所以,你能夠看到,toString()這個方法追根溯源,其實是Object.prototype.toString,在Function建立Array的時候,Object就跟着建立了Array.prototype,它就繼承了Object和Object.prototype中的數據,[1,2,3]數組對象由Array建立,所以[1,2,3]也就繼承了Array、Array.prototype、Object、Object.prototype中的數據,所以最終才能夠調用[1,2,3].toString()。blog

對於String、Boolean等構造函數,仍是自定義構造函數function f(){...}也都是這樣。

function f(){...},看上去是你寫了這個普通的構造函數,實際上這個普通的函數是Function建立的,你寫的這個f函數,因爲是Function()實例化出來的(也就是函數的f的構造函數就是Function),那麼普通函數f做爲Function構造函數的實例對象,那麼普通函數f也就會繼承Function構造函數和Function.prototype中的數據。

說來詭異的是,也是Function本身建立了本身,正是在在建立本身的時候,經過this.prototype=new Object()給本身也建立了原型對象,就是圖中藍色的原型對象,這個原型對象因爲是new Object實例化的,所以這個藍色的原型對象,也就繼承了Object和Object.prototype原型對象中的數據,這樣說來,Object的原型對象是原型鏈條中的最頂層的一個對象,而後原型鏈往下揪分裂成了兩條。

Function.prototype原型對象雖然繼承了Object.prototype中的數據,可是它本身還擴展了本身專有的屬性和方法,分別是name、length、call()、apply()、bind()這五個,而後因爲普通函數f就是由Funciton建立出來的,所以這個普通函數也就繼承了Function和Function.prototype中的數據,所以你纔可使用f.apply()仍是f.bind(this),也所以纔可使用Array.apply(),這就是圖中的第二條藍色的原型鏈。固然這條原型鏈中的數據,會被Array仍是String仍是Boolean這類構造函數繼承,可是不會被[1,2,3]這些繼承,他們不處於同一個鏈條上。

雖然Function建立了它本身,也建立了Object,但到底它是先建立本身仍是先建立Object就無從得知了。若是Function先建立了本身,那麼在它建立本身的時候,還在使用this.prototype=new Object()給本身建立原型對象時,這個Object又是哪裏來的,難道Object就已經先存在了?若是Object先於Function存在了,但Funciton都尚未存在,它怎麼去建立Object?這究竟是雞生蛋仍是蛋生雞無從得知,這也反映了javascript語言底層機制就是混亂的。

也許這一切都很繞,可是隻有理解了Function與Object,才能更清晰高屋建瓴的理解本來繁蕪繁雜和混亂的javascript。

相關文章
相關標籤/搜索