前言:
JavaScript是一種弱類型語言,變量的類型是不確定的,關于變量類型的坑比較多,本文對這些內容歸納總結,便于隨時查看。
-
JavaScript類型有哪些?
JavaScript的數據類型分為兩類:原始類型和對象類型,JS中原始類型包括,數字,字符串和布爾值,還有兩個特殊的原始值,null和undefined,他們代表了各自特殊類型的唯一成員。除此之外就是對象了,對象是屬性的集合,每個屬性都由“名/值對”構成,JS中對象是個很大的概念,可以說除了null和undefined都可以稱之為”對象“,3中原始類型可以通過構造函數來創建包裝對象,而真正的對象Object之中又包含了數組、函數、內置的日期、正則、Error這些,是不是有點暈了?
-
關于原始類型的一些坑
舉個栗子先:
var str = "test" ; //創建了一個字符串
str.len = 10; //又設置了一個屬性給他
var t = str.len; //現在查詢一下這個屬性
很奇怪的是,字符串明明是原始類型,為什么可以設置屬性?原始類型可是不可變的呀?
其實,這段代碼運行過后t的值是undefined,而變量str的值沒有變化。
這段代碼說明,在讀取字符串、數字、布爾值的屬性值(或方法)的時候,表現的像對象一樣。但如果試圖給其屬性賦值,則會忽略這個操作:修改只是發生在臨時對象身上,而這個臨時對象并未繼續保留下來。
ps:摘自JavaScript權威指南
存取字符串、布爾值、數字的屬性時臨時創建的臨時對象就稱作包裝對象,有別于真正的”對象“。但是如果用typeof
檢測一下類型,你會發現包裝對象也確實是Object
類型。
-
原始類型和引用類型本質區別
對象類型我們也通常稱作引用類型,原始類型歸根到底是不可修改的,而引用類型是可以隨時修改的。
這里說一個栗子:
var str = "hello world!";
str.toUpperCase(); //輸出結果是"HELLO WORLD!"
str; //但是這里依舊是"hello world!"
看上去是修改了字符串,實際上toUpperCase()
返回了一個新的字符串。
其實原始類型,本質上就是儲存在棧內存中的一個值,就是實打實的一個值,他們相等的條件就是值相等;而引用類型他們的值都是引用,對象的比較是引用的比較,當且僅當他們用同一個引用時他們才相等。
看了這幅圖會更好理解他:
-
undefined和null
這兩兄弟都是用來描述“空值”這個概念的,但是呢他們之間還有不同。
使用typeof null
測試發現,返回的值是"object"
,這里我們說null
的一個用法,如果定義的變量將來用來保存的是對象,我們可以把變量初始化為null
。
而undefined
會出現在以下場景中:
已聲明未賦值的變量
獲取對象不存在的屬性
無返回值的函數執行結果
函數的參數沒有傳入
void(expression)
-
JavaScript類型轉換
上幅圖:
摘自JavaScript權威指南
這里面有兩個問題重點說一下:
- 轉換和相等的關系
null == undefined;
"0" == 0;
0 ==false;
"0" ==false;
上面的這些表達式都返回true
,然而并不代表兩個值是真的相等,js中完全相等是用===
表示的,上面的這些表達式只是在比較之前都自動做了類型轉換,這樣的我們就稱作隱式類型轉換。 - 對象到原始類型的轉換
圖中我們可以看出,所有對象轉換為布爾值都是true
對象轉換為字符串,就會調用toString()
方法;
轉換為數字一般調用valueOf()
方法;
對于“+” “==” “!=”和關系運算符,如果他的其中一個操作數是對象,js就會把對象轉換成為原始值。
這里還需要了解補充
-
JavaScript類型判斷
類型識別的4種方法:
typeof
Object.prototype.toString
constructor
instanceof
typeof:
可以識別標準類型(Null除外);
不能識別具體的對象類型(除了function)
Object.prototype.toString:
可以識別標準類型以及所有內置(build-in)對象類型
不能識別自定義類型
constructor:(是對象原型上面的一個屬性,他指向了構造器本身)
識別標準類型(undefined/null除外,因為他們沒有構造器)
識別內置對象
識別自定義對象
instanceof:
能判別內置對象類型
不能判別原始對象類型
可以判別自定義對象類型以及它的父對象類型