JavaScript中的變數型別:
基本型別值:Undefined,Null,Boolean,Number和String.
按值訪問(可直接操作儲存在變數中的變數值);
複製規則:當複製基本型別值時:兩個變數完全獨立,不會互相影響。如下所示:
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。
文章僅代表個人理解,如有錯誤或補充,歡迎指出。