最近的學習中老是時不時的遇到原型相關問題,不勝困擾,因而決定學學哪吒鬧海,對「東海三太子」進行抽筋拔骨。但願你在看完本文以後感覺是這樣的:javascript
世人皆愛聽故事,在聽各類之乎者也以前不如容小生給你們講個故事。在好久好久之前,js是孤獨的,他沒爹沒媽,沒妻沒子。js轉念一想,總不能叫孤兒吧,因而美其名曰:「null先生」。有一天,null先生撿到了一隻雞和一枚雞蛋,非常高興,給雞蛋取名爲Object
,因爲他先看到雞後看到蛋,因而他認爲雞是屬於他的,這隻雞呢又是由雞蛋孵化的,爲了方便理清這層關係,他使用prototype
和__proto__
來進行區分,並規定:html
Object.prototype = 雞;
雞.__proto__ = null;複製代碼
以圖示之:java
null先生並不安分,他認爲雞給他帶來了不少樂趣,他得回報啊,因而他動手爲雞造了一個雞窩,並規定,這個雞窩是給雞的,因而:bash
雞窩.__proto__ = 雞;複製代碼
以圖示之:函數
自從有了這個雞窩,null先生今後和雞過上了沒羞沒臊的生活。。。。。。額,不是,是有了這個雞窩,雞竟然生小雞了,但凡這隻雞走進雞窩,沒多久就能從裏面產出小雞來,amazing!null先生想這確定是這個雞窩的功勞,興奮之餘,他發現雖然都是雞,但顏色,大小等都各有差別,你們都是雞,你裝什麼高貴。null先生雖然這麼想,但爲了區分仍是根據它們的特性進行命名:String
、Number
、Boolean
、Array
。。。。。。這時null先生再望向那枚起始的雞蛋,一拍大腿,雞生蛋,蛋生雞,這枚雞蛋(Object
)也能夠歸屬到雞窩纔是!學習
Object.__proto__ = 雞窩;複製代碼
null先生覺得日子總該平靜了吧,但雞就是雞,一天不搞事渾身難受,有一種渾身彩色的小雞咱們簡稱爲彩雞,它幹了什麼呢?它竟然能夠本身造窩,不只如此,它造出來的雞窩和null先生造的雞窩功能是同樣的,也能產小雞,null先生不由歎服:好你個彩雞,竟然有如此之本領,這般放蕩,要剋制本身的本性纔好。因而給這種彩雞取名爲「放克性」,彩雞不服,兄弟姐妹們都是英文名憑啥我是中文名,便自我更名Function
。有了這層關係,咱們大膽得出結論:spa
String.__proto__ = 雞窩;
Number.__proto__ = 雞窩;
...
Function.__proto__ = 雞窩;
Function.prototype = 雞窩;複製代碼
以圖示之:.net
啊~null先生大嘆一聲,這日子何時是個頭啊!其實,這纔剛剛開始。。。。。。prototype
好了,故事講完了,根據以上信息咱們得出如下結論:指針
Object.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;複製代碼
咱們常說「萬物皆對象」是由於javascript任何值或變量都是對象,可是對象也能夠劃分爲三六九等。
Javascript中全部的對象都是Object
的實例,並繼承Object.prototype
的屬性和方法,全部的對象都是間接或直接的經過Object
衍生的。這個大哥Object
當之無愧。
當咱們定義一個對象時,能夠用var obj = new Object()
,咱們都知道new
是用來實例化一個對象的方法,可是咱們都知道javascript中不存在真正的類的概念,因此只能用函數來模擬,那麼既然能夠有上面的作法也就印證了Object
也是特殊的函數。 咱們回到剛纔的故事,Object
是蛋,Function
是雞,那你以爲是雞生蛋仍是蛋生雞呢?成年人沒空思考,小孩又想不出答案。。。。。。
講了這麼多,那麼到底何爲原型,何爲原型鏈呢???
每一個函數都有prototype(原型)屬性,這個屬性是一個指針,指向一個對象,這個對象的用途是包含特定類型的全部實例共享的屬性和方法,咱們稱這種對象爲原型對象,即這個原型對象是用來給實例共享屬性和方法的。也就是說Function.prototype = 原型對象
,如今再想一想那羣雞和雞窩是否是恍然大悟,雞窩原來就是原型對象!
new
操做符生成的對象。函數對象有一個
prototype
屬性,普通對象就沒有這個
prototype
屬性,存在
__proto__
。咱們來看幾個例子:
var obj = new Object();
console.log(obj.__proto__);//Object原型對象
console.log(obj.prototype);//undefined
console.log(Object.prototype);//Object原型對象
console.log(obj.__proto__ === Object.prototype)//true
var Fn = function(){};
var fn = new Fn();
console.log(Fn.prototype);//Object {constructor: function}
console.log(fn.__proto__);//Object {constructor: function}
console.log(fn.__proto__ === Fn.prototype);//true複製代碼
實際上每一個實例內部都有一個指向原型對象的指針。所以:若var a = new A()
;則a.__proto__=A.prototype
。
談到原型鏈就不得不談到__proto__
,上面咱們有談到,每一個對象都會在其內部初始化一個屬性,就是__proto__
。當咱們訪問一個對象的屬性時,若是這個對象內部不存在這個屬性,那麼它就會去__proto__
裏找這個屬性,這個__proto__
又會有本身的__proto__
,因而就這樣 一直找下去,也就是咱們平時所說的原型鏈的概念。舉一個構造函數中常常遇到的實例:
var Fn = function(){};
Fn.prototype.sayLove = function(){
console.log("I love XX");
}
var fn = new Fn();
fn.sayLove();//I love XX;複製代碼
當咱們調用fn.sayLove()
時會輸出"I love XX",那麼fn是如何找到這個方法的呢?首先fn做爲實例對象,自己並不存在sayLove()
方法,從而它就會去找fn.__proto__
,由於fn是Fn的實例,所以fn.__proto__ = Fn.prototype
,而咱們上邊定義了Fn.prototype.sayLove = function(){}
,所以fn.sayLove()
天然也就輸出了"I love XX"。
初來貴寶地,有錢的捧個贊場,沒錢的點個關注再走。
深刻理解JavaScript原型鏈
Object.prototype原型和原型鏈
JS原型和原型鏈是什麼?
JavaScript 世界萬物誕生記