js中對數據類型的總結及判斷數據類型的各類方法及優缺點

js中的數據類型

js中只有六種原始數據類型和一個Object:jquery

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (ECMAScript 6 新定義)
  • Object

你們認真記清這個描述,不要到時候把Array、Date都當成js的數據類型就尷尬了。那可能會有人問,那Array和Date算什麼呢,他們都屬於Object,看下面分類:數組

Object分類

Object分爲 本地對象內置對象宿主對象三種

本地對象

定義:獨立於宿主環境的ECMAScript實現提供的對象。簡單的說就是ECMA定義的類。他們包括:
Object   Function   Array   String
Boolean   Number  Date RegExp
Error   EvalError   RangeError  ReferenceError
SyntaxError   TypeError URIError

因此Array和Date都屬於對象類型,它們是本地對象。瀏覽器


疑問:

1.有人可能會問,爲何String也是Object類型,上面不是說了是原始類型嗎?
答:原始類型中有字符串String不錯,它只是表達了一種數據類型,但數據類型也有本身的類定義啊,是吧,上面的String說的就是它的類型定義,是個對象,因此固然也是引用類型了。其餘同理。
看下面demo函數

var str1='hello';
var str2=new String("hello");
typeof str1 //string
typeof str2 //object

//若是想獲取str2的字符串,能夠經過str2.toString()

str1 instanceof String //false
str2 instanceof String //true

內置對象

定義:「由ECMAScript實現提供的、獨立於宿主環境的全部對象,在ECMAScript程序開始執行時出現」。這意味着開發者沒必要明確實例化內置對象,它已經被實例化了。
內置對象只有兩個 GlobalMath,他們其實也是本地對象,根據定義每一個內置對象都是本地對象。

宿主對象

全部非本地對象都是宿主對象,即由ECMAScript實現的宿主環境提供的對象。全部 BOMDOM對象都是宿主對象。

typeof

最多見的判斷方法:typeof,它的官方解釋測試

typeof操做符返回一個字符串,表示未經計算的操做數的類型。
簡單理解就是 typeof是判斷的是原始類型(值類型),但函數返回的是 function,null返回的也是 object
typeof Undefined //'undefined'
var num;
typeof num  //undefined

typeof各種型返回結果列表

類型 結果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol (ECMAScript 6 新增) "symbol"
宿主對象(由JS環境提供) Implementation-dependent
函數對象([[Call]] 在ECMA-262條款中實現了) "function"
任何其餘對象 "object"

爲何typeof null是object

在 JavaScript 最初的實現中,JavaScript 中的值是由一個表示類型的標籤和實際數據值表示的。對象的類型標籤是 0。因爲 null 表明的是空指針(大多數平臺下值爲 0x00),所以,null的類型標籤也成爲了 0,typeof null就錯誤的返回了"object"。

typeof優缺點列表

優勢 缺點
判斷原始類型比較方便 null返回的是object
方法返回的是function
全部的引用類型都返回object,Array、Date等不能準肯定位

instanceof

定義:「instanceof 運算符用來測試一個 對象(第一個參數)在其原型鏈中是否存在一個構造函數(第二個參數)的 prototype 屬性。」
簡單理解就是:instanceof是判斷兩個對象「最近」prototype是否同樣。
另外,instanceof是判斷對象是否屬於某一類型,而不是獲取的對象的類型。
var str1="hello";
var str2=new String("hello");
var arr=[1,2,3];
function person(){}
function man(){}
man.prototype=new person();
var m1=new person();
var m2=new man();

str1 instanceof String    //false
str2 instanceof String    //true
arr instanceof Array      //true
arr instanceof window.frames[0].Array  //false
m1 instanceof person      //true
m2 instanceof man         //true
m2 intanceof person       //true

優缺點列表

優勢 缺點
判斷對象的具體類型 只能判斷對象,對原始類型不能判斷
多全局對象時返回不正確

多全局對象解釋

簡單來講:多全局對象就是跨窗口或跨frame操做。

全局環境

在瀏覽器中,咱們的腳本可能須要在多個窗口之間進行交互。多個窗口意味着多個全局環境,不一樣的全局環境擁有不一樣的全局對象,從而擁有不一樣的內置類型構造函數。
這可能會引起一些問題。
好比,表達式 [] instanceof window.frames[0].Array 會返回false,由於 Array.prototype !== window.frames[0].Array.prototype,所以你必須使用 Array.isArray(myObj) 或者 Object.prototype.toString.call(myObj) === "[object Array]"來判斷myObj是不是數組。prototype


根據對象的constructor判斷

alert(c.constructor === Array) ----------> true
alert(d.constructor === Date) -----------> true
alert(e.constructor === Function) -------> true
注意: constructor 在類繼承時會出錯
eg:
      function A(){};
      function B(){};
      A.prototype = new B(); //A繼承自B
      var aObj = new A();
      alert(aobj.constructor === B) -----------> true;
      alert(aobj.constructor === A) -----------> false;
而instanceof方法不會出現該問題,對象直接繼承和間接繼承的都會報true:
      alert(aobj instanceof B) ----------------> true;
      alert(aobj instanceof B) ----------------> true;
言歸正傳,解決construtor的問題一般是讓對象的constructor手動指向本身:
      aobj.constructor = A; //將本身的類賦值給對象的constructor屬性
      alert(aobj.constructor === A) -----------> true;
      alert(aobj.constructor === B) -----------> false; //基類不會報true了;

缺點:繼承的對象判斷時,不許確。感受雞肋。指針

最靠譜的方法: Object.prototype.toString.call(obj)code

  • 這種方法不存在多全局環境和Array、null返回object的狀況,
  • 原始類型和原始類型對應的引用類型聲明的變量都能返回正確的值
  • 可是這個方法對自定義類型無效,自定義類型返回的都是Object,因此自定義時仍是使用instanceof
var str1="hello";
var str2=new String("hello");
var arr=[1,2,3];
function Man(){}
var man=new Man();
Object.prototype.toString.call(str1);   //[object String]
Object.prototype.toString.call(str2);   //[object String]
Object.prototype.toString.call(arr);   //[object Array]
Object.prototype.toString.call(man);   //[object Object]
Object.prototype.toString.call(null);   //[object Null]
Object.prototype.toString.call(/test/)  //[object RegExp]
優勢 缺點
不存在多全局環境問題 只能判斷本地對象和宿主對象
原始類型不管是字面量語法聲明仍是經過對應的引用類型聲明都能正確判斷 自定義類型都返回[object Object]

jquery.type()

就是對prototype的封裝。源碼附上:對象

type: function( obj ) {
        return obj == null ?
            String( obj ) :
            class2type[ toString.call(obj) ] || "object";
    },

對數組的判斷

var arr=[1,2,3];
typeof arr   //object  分辨不出類型
arr instanceof Array   //true //受多全局環境影響
Object.prototype.toString.call(arr);  //[object Array] //推薦
Array.isArray(arr)    //true //推薦
$.type(arr)   //array  //推薦
相關文章
相關標籤/搜索