JavaScript的幾種基礎數據類型進階
JavaScript常見的有五種基本類型:boolean,undefined,null,number,string。ES6新增了symbol。所以從嚴格意義上來說,目前JavaScript有六種數據類型。基本類型的判斷使用typeof操作符,所有基礎類型不可改變。
下面,我們來一探究竟這些數據類型與其轉換規則吧!
Boolean類型在實際的工作中被經常使用,當我們在處理某些JS的業務邏輯時,難免需要通過Boolean值來進行相關的判斷,如if,三目運算等。
與Boolean類型相關的Boolean值轉換方法是Boolean()函數。Boolean()的轉換規則如下
Boolean(true); // true
Boolean(false); // false
Boolean(undefined); // false
Boolean(""); // false
Boolean(" "); // true
Booleam({}); // true
Booleam([]); // true
Boolean(NaN); // false
需要注意的是Boolean函數是if語句的隱式轉換規則(括號內爲非表達式):
var messeage = " ";
if(messeage) { // 這裏if語句進行了隱式轉換,對message調用Boolean方法
console.log(message); // " "
}
在使用邏輯非操作符時,這裏有一個你可能不知道的騷操作:
!!true; // true
!!false; // false
!!undefined; // false
!!""; // false
!!" "; // true
!!{}; // true
!![]; // true
!!NaN; // false
// 你發現了嗎?
兩個邏輯非操作轉換成Boolean值的結果和Boolean()方法相同。
當然,可以通過new操作符對Boolean函數進行實例化,此時的Boolean爲構造函數,可以傳入一些參數。
undefined表示當前的變量沒有被賦值,它是全局對象的一個變量,不可修改,枚舉,配置。
var a;
typeof a; // undefined
typeof b; // undefined,沒有報錯
a === "undefined"; // true,注意:這裏是'==='
b === "undefined"; // Uncaught ReferenceError: b is not defined
通過typeof操作符能判斷一個未聲明或者已聲明未賦值的變量是否是undefined。但是在實際中應該避免未聲明變量的基本類型判斷,因爲它並不適合用於判斷對象的屬性是否存在。
或者細心的你會發現:
// 當JavaScript運行完某個函數時
function test() {
var a = 100;
console.log(a);
};
test();
// 打開瀏覽器控制檯,你會看到以下輸出
// 100
// undefined
所以,當函數沒有明確的返回值(return nothing)的時候,它會默認返回一個undefined。
學到了嗎?我們可以通過typeof判斷某個變量是否未定義,或者你可以這樣寫:
var non;
// 常規的判斷方法
if(typeof non === "undefined") {
// ...
};
// 替代typeof的方法
if(non === void 0) {
// ...
};
// 所以你會看到這樣一個神奇的效果
undefined === void 0; // true !!!
判斷某個變量未定義,可以判斷它是否等於void 0
或者void(0)
,或許你已經在HTML中見識過它的強大了
<a herf="javascript: void(0)">這是一個超鏈接</a> <!-- 點擊後不幹任何事 -->
用void 0
代替undefined,可以避免undefined被重寫。
首先,null不是一個屬性,它是一個值(字面量),它也是一個指針,指向一個空對象的引用。
只有在我們主動將某個變量的值設置爲null時,這個變量才能爲null
var a = null;
a; // null
這裏有一個需要注意的問題:
null == undefined; // true,其實是 == 的隱式轉換規則導致
null === undefined; // false
-
Number類型
Number是JavaScrit幾種基本類型中最複雜難理解的類型,它包含的幾種數值轉換方法中總有一些讓人費解的地方,雖然在實際的項目中可能並沒有很大的意義,但還是需要將其理解透徹,以備不時之需,或者說在遇到問題時才能精準定位。
Number包含兩種數值類型:整數和浮點數(或許在其他強類型語言中,字符串有單雙進度之分,但對於JS來說,它只表示雙精度浮點數,記住了!)
-
無窮值Infinity
在JavaScript中,數值有大小正負之分,所以無窮值也有正無窮+Infinity
(Number.POSITIVE_INFINITY)
和負無窮-Infinity(Number.POSITIVE_INFINITY)
,ECMAscript中最小值保存在Number.MIN_VALUE
中,如果某個值小於它,那這個值就是-Infinity,對應的最大值爲Numner.MAX_VALUE
。Infinity的計算有些難以讓人理解:
Infinity + 1; // Infinity; Infinity + Infinity; // Infinity; Infinity - Infinity; // NaN -Infinity + Infinity; // NaN 0 / 0; // NaN
再看看下面這段取最大值的代碼:
let arr = [1,5,3,7,2]; let maxVal = 0; arr.forEach(item => { if(item > maxVal) maxVal = item; }) console.log(maxVal); // 7 // 這段代碼有問題嗎?
如果我們不知道arr數組裏面具體的數據(可能全部爲負值),那麼這段代碼能拿到數組中的最大值嗎?
答案顯然是拿不到,原因是
maxVal = 0
導致0始終是最大值,所以maxVal應該初始化爲一個無限小的數值-Infinity:let maxVal = -Infinity;
這就是Infinity的一個實際應用場景。
判斷一個數值是否是無窮可以使用isFinite(),ES6新增了Number.isFinite();
-
非數值NaN
NaN是一個數值,通常表示一個計算錯誤時的返回值,看代碼:
typeof NaN; // number Math.sqrt(-1); // 嘗試對一個負值求平方根,它將會返回NaN
NaN雖然是一個數值,但是NaN的任何操作都會返回NaN:
NaN/0; // NaN NaN == NaN; // false NaN === NaN; // false NaN != NaN; // true NaN !== NaN; // true
判斷一個變量是否是數值可以使用isNaN(),ES6新增了Number.isNaN();
a) isNaN()
而在ES6之前,判斷一個值是否是NaN的規則如下:
判斷參數是否是Number類型,如果是,則返回true;
如果不是,調用Number()方法,將其轉換爲Number類型;
然後判斷轉換後的值是否不恆等於(!==)它自己
// isNaN的實現 var isNaN = function(value) { var nan = Number(value); return nan !== nan; // 此處運用到了NaN !== NaN }
所以,我們可以通過NaN的實現對一些難以理解的結果作出更好的解釋:
isNaN(NaN); // true Numer(NaN) == NaN; NaN !== NaN; true isNaN('red'); // true Numer('red') == NaN; NaN !== NaN; true isNaN(true); // false Number(false) == 0; 0 !== 0; false isNaN({}); // true Number({}) == NaN; ... ... isNaN([]); // false Number([]) == 0; ... ...
isNaN另一個強大的地方在於:可以通過它來確定某個值是否可以參與數學運算:
function isCompute(x) { if(isNaN(x)) console.log(x + ' can not be computed!'); }
b) Number.isNaN()
相比於
isNaN()
,Number.isNaN()
方法會將傳入的參數轉化成數值再判斷,因爲它更專注於number類型,其判斷條件更爲苛刻。實現如下var Number.isNaN = function(x) { return typeof x === 'number' && isNaN(x); }; Numer.isNaN(NaN); // true Number.isNaN(true); // true Number.isNaN({}); // true Number.isNaN([]); // true // 從直觀的角度來看,[]不能表示爲一個數值。
NumberisNaN()
的參數只接受數值,如果要讓它返回true,這個數值必定爲NaN。 -
數值轉換
Number類型的數值轉換有三種:Number()、parseInt()和parseFloat()。
a) Number()
Number()函數的轉換規則如下:
類型 值 true 1 false 0 null 0 undefined NaN {} NaN [] 0 ‘[]’ NaN [2] 2 [2,1] NaN 十六進制數 十進制數 其他非空對象 對象的valueOf() 等於NaN ? 調用toString() b) parseInt()
相比於
Number()
,parseInt()
是更爲嚴格的轉換形式,它是通過查找的方式找到數字,直到遇到第一個非空格字符,如果第一個字符不是數字或者負號,就會返回NaN。它可以接受第二個參數,表示轉換的進制:當parseInt傳入的第一個參數是字符串時,它會對字符串的每個字符挨個進行數值轉換;當傳入的第一個參數不是字符時,它會嘗試將這個參數轉化成十進制的字符串,然後再根據第二個參數對字符串按個轉換。
parseInt('1234a'); // 1234 parseInt('10', 8); // 8 8進制的10轉換成10進制:1*8^1 + 0*8^0 = 8 parseInt('0x10', 16); // 16 16進制的0x10轉化成10進制:12 parseInt('0x10', 8); // 0 8進制的0x10轉化成10進制:x是8機制不能解析的字符 parseInt(0x10, 8); /* 14 0x10爲16進制,轉換成10進製爲16,所以相當於 parseInt('16', 8); */
c) parseFloat()
parseFloat
只能解析十進制,他和parseInt
大致相同,但是返回的是浮點數,這裏就不再贅述。
-
-
String類型
String類型表示由16個Unicode字符組成的元素,將其他類型的值轉換成字符串主要有:toString()、String()。
區別:
toString()
是一個屬性方法,調用只能通過點語表示法調用,而且null
和undefined
沒有這個方法,ES6新增:function.prototype.toString()
,toString()
可以傳入一個參數,表示輸出的進制數;String()
是一個構造函數,可以將null和undefined轉換成對應的字符串。// 可以自己實現一個String方法並設置一些參數 var String = function(value, hex){ if(value === 'null') return 'null'; else if(value === 'undefined') return 'undefined'; elee return value.toString(hex); }
-
Symbol類型
Symbol類型是ES6新增的基本數據類型,也可以將它成爲atom(原子),它主要是用於設置對象的屬性值,通過Symbol()構造函數可以給對象添加一個匿名屬性(此時的鍵和值都是實例化的Symbol對象,且對象不可枚舉)
Symbol('a') !== Symbol('a'); // true var a = Symbol(); typeof a ; // symbol let ob = {}; obj[a] = ‘a’; JSON.stringfy(obj); // '{}'
如需查看Symbol更詳細的內容,請點擊MDN Symbol
JavaScript基礎類型基本就這些了,內容如有不準確的地方,歡迎指正。
貴有恆何必三更眠五更起,最無益只怕一日曝十日寒。