javascript 理解 typeof, instanceof and constructor

來源:互聯網
上載者:User


   我們假設要寫個isArray() 的方法,當然ecmascript5 已經添加了這個方法,(>ie8)
   首先我們使用typeof:
   在ECMAScript 中有5中基礎資料型別 (Elementary Data Type),Undefined、Null、Boolean、Number、String,還有一種複雜的資料類型,即:Object

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object

   MDN Description:All objects in JavaScript are descended from Object; all objects inherit methods and properties from Object.prototype, although they may be overridden
   在javascript中,Object是'祖先',所有objects都是Object的子,並從Object.prototype下繼承屬性和方法。

   使用typeof時要注意的就是typeof null = "object";   
    var arr=new Array();
    typeof arr === "object";//true
   顯然只用typeof 是不行的,無論引用的是什麼類型的對象,它都返回 "object"。然後我們就會想到instanceof或constructor
    arr instanceof Array; // true   
    arr.constructor === Array; // true
   但是在不同iframe下,就不行了!
    var iframe = document.createElement('iframe');   
    document.body.appendChild(iframe);   
    xArray = window.frames[window.frames.length-1].Array;   
    var arr = new xArray(1,2,3); // [1,2,3]   

    arr instanceof Array; // false   
    arr.constructor === Array; // false  

    MDN Description:Different scope have different execution environments. This means that they have different built-ins (different global object, different constructors, etc.).
    
    下面具體解釋!
    先說constructor
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor
    MDN Description:All objects inherit a constructor property from their prototype。
    所有的objects 都從它們的prototype繼承了constructor屬性。而這個constructor指向了這個object本身,也就是所謂的建構函式!即 Array.prototype.constructor === Array
    所以上面的 arr.constructor === Array;

    但是在不同iframe下,由於每個iframe都有一套自己的執行環境,不同的執行環境具有不同的原型鏈, 接著上面的代碼,xArray.prototype === Array.prototype  //false ,
    所以上面的 arr.constructor !== Array;   
    

    再說下instanceof,這個有點複雜,耐心看!

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

    MDN Description:The instanceof operator tests presence of constructor.prototype in object prototype chain.
    instanceof 用來判斷 建構函式的原型是否存在於 某個object的原型鏈上
    這句話翻譯過來很難理解,說簡單點,instanceof 用於判斷一個變數是否是某個object的執行個體。
    我們來看看instanceof 的原理,這樣就會理解那句話了!


    首先解釋下原型,在 JavaScript 原型繼承結構裡面,規範中用 [[Prototype]] 表示對象隱式的原型,在 JavaScript 中用 __proto__ 表示,並且在 Firefox 和 Chrome 瀏覽器中是可以訪問得到 


    這個屬性的,但是 IE 下不行, 這個屬性指向它的原型對象。在 JavaScript 裡用 prototype 屬性工作表示顯示的原型,這個大家都知道;
    當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那麼他就會去__proto__裡找這個屬性,這個__proto__又會有自己的__proto__,於是就這樣一直找下去,你可以再Chrome下輸入 


   一個對象,比如window,然後點開,在最下面就會看到__proto__,點開__proto__,最下面又有__proto__,這個就是javascript的原型鏈!
   關於__proto__,https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto


    讓我們看下instance_of 的一段代碼

 function instance_of(L, R) {//L 表示左運算式,R 表示右運算式
     var O = R.prototype;// 取 R 的顯示原型,即建構函式的原型(這裡說建構函式是配合上面的英文)
     L = L.__proto__;// 取 L 的隱式原型
     while (true) { //迴圈尋找object的原型鏈
     if (L === null) 
        return false; 
     if (O === L)// 建構函式的原型存在於 某個object的原型鏈上
        return true; 
     L = L.__proto__; //繼續尋找
    } 
 }

這段代碼是一篇部落格裡copy的,應該是段虛擬碼!它很清楚的表達的instance_of的原理,也解釋了上面的英文!

重新組織下語言,可以這樣說: 如果'類'(建構函式)的原型與對象(object)原型鏈上的某一個原型是同一個對象,那麼instanceof運算將返回true。
理解了原理,我們再回到上面的 var arr=new Array();
由於Array.prototype === arr.__proto__;//true
所以 arr instanceof Array; // true  
在不同iframe下,arr instanceof Array; // false ,這個在constructor裡已經解釋了,即:不同的執行環境具有不同的原型鏈!

上面是借isArray來分析 typeof, instanceof and constructor 這三個東東!

但是isArray到底該怎麼來實現的!查看了下jquery的源碼,和mdn的大同小異!

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

主要原理是利用了Object.prototype.toString()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString
MDN Description:If this method is not overridden in a custom object, toString() returns "[object type]"
如果這個方法沒有被重載的話,它會返回"[object type]",即可以得到對應的類型!(更詳細的返回值可以通過http://www.ecma-international.org/ecma-262/5.1/或http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf來查看)
Object.prototype.toString()可以判斷所有的內建類型,這裡只是用Array舉例而已!
看下面代碼!

  var isArray = function (vArg) {
    return Object.prototype.toString.call(vArg) === "[object Array]";
  };

call改變toString的this引用為待檢測的對象,返回此對象的字串表示,然後對比此字串是否是'[object Array]',以判斷其是否是Array的執行個體。
也許你要問了,為什麼不直接o.toString()?嗯,雖然Array繼承自Object,也會有toString方法,但是這個方法已經被改寫了!不能返回type;詳情看https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString或上面的http://www.ecma-international.org/ecma-262/5.1


參考部落格:
http://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/   //instanceof
http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930548.html //constructor
http://blog.csdn.net/isea533/article/details/7248520  //isArray

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.