js的8種數據類型
JavaScript中有8種數據類型, 包括基本數據類型(number, string, boolean, null, undefined, symbol, bigint)和引用數據類型object
number
JavaScript中的整數和浮點數都會按照浮點數的標准進行存儲.
即64個二進制位, 從最左邊開始:
第1位: 符號位, 0表示正數, 1表示負數
第2到第12位: 存儲指數部分
第13到第64位: 存儲小數部分
其中, 符號位決定一個數是正數還是負數, 指數部分決定了一個數的大小, 小數部分決定了一個數的精度
數值精度
JavaScript提供的有效數字最長為53個二進制位, 這意味着絕對值小於2的53次方的整數都能夠精確表示
JavaScript內部實際的表現形式:
(-1)^符號位 * 1.xxx...xxx * 2^指數
Math.pow(2, 53) === Math.pow(2, 53) + 1
0.1 + 0.2 = 0.30000000000000004就是因為精度缺失的原因, 還有人因此做了一個網站: (http://0.30000000000000004.com/)
Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER分別表示js的最大安全數和最小安全數
數值范圍
指數部分的最大值是2047(2^11 - 1), 分出一半表示負數, 那么JavaScript能夠表示的數值范圍為21024到2(-1023)
Number.MAX_VALUE和Number.MIN_VALUE代表js可表示的最大數字和最小數字
當一個浮點值大於(小於)js所能表示的最大(最小)值時, 其結果是Infinity(-Infinity), 12/0返回Infinity, -12/0返回-Infinity
NaN
NaN表示not a number(非數字), NaN和任何值都不相等, 包括它自己. 所以x != x當且僅當x是NaN時成立. 0/0會返回NaN
- Number.isNaN(Number.NaN)
- x != x 可以用來檢測x是否是NaN
- Number.isFinite()可以用來檢測Number.NaN和Infinity.
bigint
bigint可以使用任意精度表示整數. 即使超出js的安全數, 也可以安全地存儲和使用大整數
bigint不能表示小數
BigInt(123)
string
js中的字符串是不可變的, str.length可表示字符串的長度
基本數據類型字符串它不是對象, 卻能夠使用對象才有的屬性和方法進行操作(比如str.length, str.split('-')), 這是因為三個關鍵的基本數據類型都有自己對應的對象(Number, String和Boolean). 這三個對象是針對數字, 字符串和布爾值的包裝.
當我們在對象環境中使用字符串時(比如使用str.length), JavaScript會為這個字符串內部地創建一個String對象, 這個對象就代替了原始的字符串值來執行相應的操作. 注意此時被創建的String對象只是瞬時存在的, 使用之后系統就會自動將其丟棄.
boolean
null, undefined, 0, -0, NaN, ''都可以轉成false
null和undefined
null == undefined會返回true, null === undefined會返回false
symbol
symbol代表獨一無二的值
let s = Symbol(); // 這樣就生成了一個唯一不可變的值
let s1 = Symbol('s1'); // 參數表示對symbol值的描述
let s2 = Symbol('s1'); // s1 == s2會返回false
let a1 = Symbol.for('aa');
let a2 = Symbol.for('aa'); // a1 === a2會返回true
- 用symbol作為對象的屬性名時, 不能通過點去訪問屬性, 通過點訪問, js會將屬性名解析成字符串
- JSON中無法存儲Symbol類型的值
- 不可枚舉: 當Symbol值作為對象屬性名時, 可以保證對象不會出現重復的屬性, for in等方式無法枚舉Symbol值出來, 可以調用Object.getOwnPropertySymbols()獲取Symbol值. 借助Symbol的不可枚舉特性可以在js中模擬私有變量
object
對象是通過調用特殊的構造函數創建的, 常常要使用到的對象有以下:
- function: JavaScript的函數是具有可執行代碼的對象, 可以通過調用函數執行某些操作
- array
- class
- Date日期
- RegExp正則表達式
- 匹配所有中文字符, 匹配郵箱
- Math數學
- Math.ceil(), Math.floor()
- Math.round(), Math.random()
- JSON
- null, NaN, Infinity, -Infinity, 正則對象和undefined都會被轉成null
- JSON.parse(JSON.stringify())
- Error: 程序中發生的語法錯誤和運行時錯誤的對象
數據類型判斷
typeof
- 對於非object的基本類型, 除null以外, 均可返回意料之中的結果
- 對於引用類型, 除function以外, 一律返回object
- 對於null, 返回object
- 對於function, 返回function
- typeof(typeof a)返回的是string
因為typeof NaN會返回number, 但是NaN不能用於數值計算, 所以在使用typeof判斷數字時, 建議這樣子做: typeof num == 'number' && Number.isFinite(num)
instanceof
A instanceof B是用來判斷B的原型是否在A的原型鏈上
instanceof的問題在於它假定只有一個全局執行環境, 如果存在兩個及以上的全局執行環境, 那么就存在不同的構造函數, 此時instanceof無法進行判斷
Object.prototype.toString.call
Object.prototype.toString.call(true) === '[object Boolean]'
constructor
當聲明定義一個構造函數時, js會為構造函數添加一個prototype屬性指向構造函數的原型對象, 這個原型對象會有一個constructor屬性指向構造函數. 而當使用new和構造函數創建一個實例對象時, 實例對象會繼承原型對象的constructor屬性
let a = [], b = 100;
a.constructor == Array
b.constructor == Number
當程序員重寫prototype指向之后, 原來的constructor就會丟失
使用JavaScript寫一個判斷數據類型的函數
function getType(data) {
if(data === null) return 'Type: null';
else if(data === undefined) return 'Type: undefined';
else if(typeof data == 'number' && Number.isFinite(data)) return 'Type: number';
else if(typeof data == 'string') return 'Type: string';
else if(typeof data == 'boolean') return 'Type: boolean';
else if(typeof data == 'function') return 'Type: function';
else {
let tmp = Object.prototype.toString.call(data);
return 'Type:' + tmp.slice(7, tmp.length-1).toLowerCase();
}
}