JavaScript變數型別檢測總結

阿儂醬發表於2018-06-21

JavaScript中的變數型別:

基本型別Undefined,Null,Boolean,NumberString.

按值訪問(可直接操作儲存在變數中的變數值);

複製規則:當複製基本型別值時:兩個變數完全獨立,不會互相影響。如下所示:

var a = b = 1;
var c = a;
b = 2;
c = 3;
console.log(a); //1
console.log(b); //2
console.log(c); //3

引用型別值包含多個值的物件,是一種將資料(屬性)與功能(方法)組織在一起的資料結構。

按引用訪問(不能直接操作物件的記憶體空間,操作的實際上是物件的引用);

複製規則:當複製引用型別的值時,複製的其實是一個指標,該指標指向堆中的同一個物件;所以原變數和複製的變數實際上將引用同一個物件,即改變其中一個,另一個也會跟著變化。如下所示:

var cat = new Object();
var dog = cat;
dog.name = "tom";
console.log(cat.name); //tom

變數型別檢測:

方法一:type of

有兩種寫法typeof xxx ,typeof(xxx)

typeof 2 //   number
typeof null //   object
typeof undefined //  undefined
typeof `123` //    string
typeof true //     boolean

typeof {} //   object
typeof [] //   object
typeof (function(){}) //  function
typeof new Object() //object
typeof Object //function
typeof /[hbc]at/gi //object

可以看到,用type of 可以很好的區分出number,undefined,string,boolean這四種基本資料型別,但null會被判定為object.此外,該方法還能檢測出函式和物件,但是並不能知道某個物件具體是什麼型別的例項。

 

方法二:constructor

每一個物件例項都可以通過 constructor 屬性訪問它的建構函式:

var cat = new Cat();
console.log(cat.constructor === Cat) //  true
console.log(cat.constructor === Cat.prototype.constructor) //  true

其實這裡的constructor屬性並不是例項本身的,而是例項在其原型鏈上找到的屬性,即cat.__proto__物件的屬性,而由原型規則(我的另一篇部落格寫了原型規則)我們知道,cat.__proto__.constructor === Cat,所以繼承到該屬性後,cat.constructor === Cat

參考文獻:https://blog.csdn.net/zengyonglan/article/details/53465505

 

方法三:instanceof

一般用法:如果被檢測變數是給定型別的例項,則返回true。

var strObj = new String(); 
strObj instanceof String //true
strObj  instanceof Object //true

如圖所示,strObj是String型別的例項,故返回true,另外,由於所有物件都是Object型別的例項,故第三行也返回true。

但其實該方法並沒有這麼簡單,首先說明一點:JS中例項物件的隱式原型.__proto__ === 其建構函式的顯式原型.prototype;該方法就是檢測左側的__proto__原型鏈上,是否存在右側的prototype原型;即L.__proto__.__proto__ ….. === R.prototype ?如果存在返回true 否則返回false。所以所有的例項 instanseof Object 都返回true ,比如上述程式碼第三行,然而例項strObj並不是Object直接new出來的例項。那麼怎麼判斷出該例項是否是某建構函式直接new出來的例項呢?可以結合上述constructor屬性:

strObj.__proto__.constructor === String; //true

strObj.__proto__.constructor === Object; //false

便可以準確的判斷出strObj的直接和建構函式是String而非Object了。

 

關於instanceof和原型鏈的原理下面兩篇文章說的比較清楚:

https://www.cnblogs.com/libin-1/p/5820550.html

https://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/

這種方法較為穩妥,卻不能具體的檢測出某個變數的具體型別。那有沒有一種方法可以準確的檢測出某個變數的型別呢?方法4便是:

 

方法四:Object.prototype.toString.call()

1.判斷基本型別:

Object.prototype.toString.call(null);//”[object Null]”
Object.prototype.toString.call(undefined);//”[object Undefined]”
Object.prototype.toString.call("abdaw");//”[object String]”
Object.prototype.toString.call(1);//”[object Number]”
Object.prototype.toString.call(true);//”[object Boolean]”

2.判斷原生引用型別:

//函式型別:
var foo = Function()
console.log(Object.prototype.toString.call(foo))//”[object Function]”
//日期型別:
var date = new Date();
console.log(Object.prototype.toString.call(date))//”[object Date]”
//陣列型別:
var arr = [1,2,3];
console.log(Object.prototype.toString.call(arr))//”[object Array]”
//正規表示式:
var reg = /[hbc]at/gi;
console.log(Object.prototype.toString.call(reg))//”[object RegExp]”
//自定義型別:
function Cat(name) {
this.name = name;
}
var cat = new Cat("Tom");
console.log(Object.prototype.toString.call(cat)) //”[object Object]”

然而這種方法不能準確判斷cat是Cat類的例項,這時可以結合instanceof 操作符來進行判斷:person instanceof Person //true。

文章僅代表個人理解,如有錯誤或補充,歡迎指出。

相關文章