首先要認識到,typepof是一個運算符,其運算須要一個參數,返回值是參數的類型。架構
typeof parameter //使用方法1 typeof (parameter) //使用方法2....這兩種方式是等效的。
typeof null; //"object」
instanceof也是一個運算符,運算過程當中也須要一個參數,判斷某一個對象是不是所給的構造函數的一個實例,返回值是true或者false;函數
parameter1 instanceof parameter2 //使用方法 第一個參數是一個對象,第二個參數是一個函數
parameter1 instanceof (parameter2) //兩種方法等效
console.log(null instanceof Object); //false console.log(true instanceof Boolean); //false console.log(10 instanceof Number); //false console.log("sad" instanceof String); //false
2.對於一個對象,判斷其是不是某一個構造函數的實例;
var object={}; console.log(object instanceof Object);//true function A(){} console.log(A instanceof Function);//true var B=function(){}; var b=new B(); console.log(b instanceof B);//true
typeof的原理比較簡單,主要根據一個其數據類型來返回值。這裏咱們主要講解下instanceof的工做原理.spa
看下面一道例題:prototype
var Animal = function () { }; var Dog = function () { };
//子類繼承父類的函數 function extend(subClass, superClass) { var prototype = Object.create(superClass.prototype); subClass.prototype = prototype; subClass.prototype.constructor = subClass; } extend(Dog, Animal); var dog = new Dog();
console.log(dog instanceof Dog);//true console.log(dog instanceof Animal);//true
上面的這道例子,聲明瞭兩個類,動物和狗.用狗類實例化一個對象dog.按咱們的理解,dog固然屬於狗這一類,當時,狗難道不是動物嗎? 因此上述兩種輸出結果都輸出true.是合理的。設計
上述代碼執行完畢後,內存中的狀況大體是這麼樣的!code
知道了內存中的狀況,下面咱們來分析一下,代碼的執行過程。對象
執行dog instanceoof Dog的時候blog
在判斷dog對象是不是Dog類的實例的時候,繼承
1.解釋器判斷dog是不是一個對象,否不是一個對象,則返回false.如果一個對象則跳到第二部。
2.解釋器先取得dog的內置屬性,而後去取的Dog的函數原型(prototype)。
3.比較dog的內置屬性和Dog.prototype是不是同一個對象,如果則返回true.圖片
在執行到第3步的時候,由於則返回true.該句執行結束。
執行dog instanceoof Animal的時候
按照上述步驟執行到第三部,判斷dog的內置屬性和Animal.prototype不是一個對象,此時接着執行下一步
4.若dog對象的內置屬性和Animal類的原型不是同一個對象,則取出dog的內置屬性所指向的對象的內置屬性
5.判斷dog內置屬性所指向對象的內置屬性是否和Animal.prototype是否指向同一個對象,如果則返回true.
不然,沿着對象內置屬性鏈一直向上查找,一直追溯到null(Objece.prototype.__proto__==null)爲止。
簡而言之,instanceof比較的時候,
比較的規則是拿對象上的內置屬性鏈上的全部對象與給定的構造函數的原型(prototype)一一比較,直到找到相等的爲止。
若比較到最後仍然沒有發現二者相等,則返回false.
一切皆是對象,這話要從何提及呢!! 看下面的一段代碼?
console.log(Function instanceof Object); //true function a() { }; console.log(a instanceof Object); //true
若是連函數(function)都是對象,以及函數的構造函數(Function)也是對象,那麼咱們的確沒有理由反對一切皆是對象。可是,怎麼證實函數以及函數的構造函數都是對象,這些又是怎麼設計的呢?
咱們知道,若是是對象。那麼身爲一個對象,就必須具有對象中最基本的一個屬性-----內置屬性(內置屬性是任何對象都有的一個屬性),並且,內置屬性最初都起源於Object.prototype.若是這麼說的話,那麼,咱們能夠得出一個結論,即 Function和fucntion都具備一個內置屬性,且該內置屬性直接來自或者間接來自Object.prototype.
如今咱們用代碼來證實一下是否是這個樣子:
console.log(Function.__proto__.__proto__==Object.prototype); //true
若是這個輸出結果是真的,那麼在內存中的結構就應該是這麼個樣子:
說道這裏,咱們能解釋了Function是一個對象。接着咱們來解釋function也是一個對象。
一樣的道理,function既然是一個對象,那麼確定也有內置屬性,並且function是Function的一個實例,因此其內置屬性確定來源於Function.prototype.那麼Function.prototype是什麼呢?
console.log(Function.__proto__==Function.prototype);//true
講到這裏,是否是明白了什麼呢? 原來Function的內置屬性和其原型屬性居然是同一個對象。 好,進行到這裏,咱們就來一張綜合圖來分析一下,function Function Object.prototype三者間的關係。
到這裏咱們算是揭示了一切皆是對象的設計。可是若是想要理解整個設計的架構,咱們還須要搞明白一些事情?
即 從圖中咱們看出,
1.Function的對象的內置屬性的constructor指向Function.
由於constructor指向Function ==> Function.__proto__是Function的一個實例 ==> Function.__proto__是一個函數。 ok...證實一下:
console.log(typeof Function.__proto__);//function 這裏不要用instanceof判斷,若是用instanceof判斷,返回結果是false.要想查明緣由,請看instanceof工做原理。
到這裏也就證實了咱們的推論。可是,下面的一個問題來了,全部的對象都有一個內置屬性啊。換句話說,Object函數應該有一個內置的[[_proto_]]屬性,而Object.prototype也應該有一個內置的[[_proto_]]屬性。ok..上面的這幅圖片,若是補充完整的話,結果應該以下所示:
上面這幅圖片上,咱們能夠看出,不管一個對象的構造函數是誰,其內置屬性最終會迴歸到最上層的Object.prototype.因此,也就是說一切皆是對象,這句話,不僅是說說而已。
注: 上面的這幅圖片理解起來不是那麼容易。
因此,下面咱們來談談,怎麼看懂上面那副圖片?
從美學的角度來講,上面的那種設計圖真的談不上美觀,第一,它不簡單,七拐八繞。第二,很難看出來圖片想要表現的是什麼!
看懂上面那幅圖片,須要有三個最基本的指導思想,
1.一切皆是對象。
2.對象總有一個內置屬性,且該內置屬性指向其構造函數的prototype屬性。
3.函數總有一個prototype屬性,該函數在實例化的實話,該屬性賦值給實例的內置屬性。
明白了上面的三點,下面的幾段代碼,看看你是否可以回答正確?
function a() {}; console.log(a.__proto__ == Function.prototype); console.log(Function.__proto__ == Function.prototype); console.log(Function.__proto__.__proto__ == Function.prototype) console.log(Object.__proto__ == Function.prototype); //這些代碼是爲了證實第二點,第一點咱們在2.1中已經證實
function a() {}; console.log(a.__proto__ == Function.prototype);
var object={}; console.log(object.__proto__==Object.prototype) //這些代碼是爲了證實第三點
正由於有上述三種知道指導的存在,因此咱們纔會使得JS有那麼眼花繚亂的效果。
如今,你按着這三種知道思想來考慮一下,是否有比上張圖片更好的設計呢!!
注: 在JS中,並非嚴格的面向對象,能夠說,一切只是技巧的堆砌。不過,這門語言給人的啓發的確能夠引人深思----面向對象是否有更好的設計呢?
總結的部分,其實就是列出一下這篇文章中寫做的重點。
首先,分析下typeof和instanceof的比較,目的是掌握instanceof的工做原理。由於在第二部分中,須要大量使用這個函數。
其次,咱們逐步分析,一切皆是對象這個觀點。而後,用實例來證實觀點。
再次,證實一切皆是對象以後,接着來分析,用圖片一步步引出,整個設計的輪廓,重點是掌握最後一張圖片。由於全部的目的 都是爲了證實最後一張圖片。
最後,提出這種設計的核心指導思想。你能夠比照着這種指導思想仔細閱讀第二部分。