JavaScript – 数据类型
前言
写着 TypeScript 教程,顺便也写点 JavaScript 的。
参考
JavaScript 数据类型
JavaScript 一共有 8 种类型:
-
string
-
number
-
boolan
-
undefined
-
null
-
object
-
symbol (es6)
-
bigint (es2020)
symbol 和 bigint 是后来(es6 和 es2020)加进去的。
除了 object 以外,其余 7 种被称为原始类型(primitive type),它们都属于值类型(value type)。
object 被称为非原始类型(non-primitive type),它是引用类型(reference type)。
typeof
typeof 可以 detect 出 value 的类型(虽然不是很精准)
console.log('string', typeof ''); // typeof 字符串返回的是 'string'(也就是 string 类型的意思)
console.log('number', typeof 0); // 整数或浮点数是 'number'
console.log('boolean', typeof true); // true,false 是 'boolean'
console.log('undefined', typeof undefined); // undefined 是 'undefined'
console.log('null', typeof null); // null 是 'object'
console.log('object', typeof {}); // 对象是 'object'
console.log('symbol', typeof Symbol()); // Symbol 创建的是 'symbol'
console.log('bigint', typeof (100n)); // 整数+n 是 'bigint'
效果

都挺直观的,只有一个比较奇葩 —— null 是 'object',这是个历史错误,by right 它应该要是 'null' 才对。
其它常见 value 的 typeof
console.log('array', typeof []); // array 是 'object'
console.log('function', typeof function() {}); // 函数是 'function'
console.log('arrow function', typeof (() => {})); // 箭头函数是 'function'
console.log('date', typeof new Date()); // Date 实例是 'object'
console.log('reg', typeof /\d/gi); // 正则表达式是 'object'
console.log('NaN', typeof NaN); // not a number 是 'number'
console.log('class', typeof class{}); // class 是 'function'
效果

typeof 函数和箭头函数返回的是 'function'。
不过,'function' 其实不是一种类型哦,它算是 'object' 的一种。
另外,class 的本质是函数,所以 typeof class 返回 'function'。
new RegExp 和 new Date 返回的是实例,实例就是对象,所以是 'object'。
NaN 是 "not a number",虽然名字是 "不是一个 number",但其实它依然是 'number' 类型。
array 不是一种类型,它算是一种 'object'。
总结
typeof 可以返回 value 的类型信息,但它不直接等于 JavaScript 的 8 种类型。
我们需要自己进一步将其归类,比如:
typeof null 返回 'object',但 null 其实不是 object 类型,它是 null 类型才对。
typeof class、typeof function 返回的是 'function',但 JavaScript 没有 function 类型,它应该要被归纳为 object 类型。
其它判断方式
除了 typeof, 还有一些常用的类型技巧:
判断 null
null === null
判断 NaN
Number.isNaN(NaN)
判断 Array
Array.isArray([])
判断 Date 或 Regex
const date = new Date();
date instanceof Date; // true
黑魔法 typeof
console.log('string', Object.prototype.toString.call('string').slice(8, -1).toLowerCase());
效果

null 不是 'object' 而是 'null'。
Array 不是 'object' 而是 'array'。
Date 不是 'object' 而是 'date'。
Regex 不是 'object' 而是 'regexp'。
结论:透过 Object.prototype.toString 来做 typeof 可以判断的更仔细。
类型转换
参考:阮一峰 – 数据类型转换
先提醒:JavaScript 的类型转换规则挺乱的,最好不要常用,如果非要用,那要记好规则。
所有类型都可以强转成 boolean、string、number。
转 boolean
Boolean(value) 或者 !!value,两种写法都可以把 value 强制转换成 boolean。
它的规则是:除了以下 5 个 value 会转成 false,其它 value 都会转成 true。
-
undefined
-
null
-
+0 或 -0
-
NaN
-
''(empty string)
像 emtpty object {}、empty array [] 这些都会转成 true。
转 number
Number(value) 或者 +value 两种写法都可以把 value 强制转换成 number。
-
'123'→123 -
''→0 -
true→1 -
false→0 -
'123abc'→NaN -
undefined→NaN -
null→0
知识点:
-
boolean
true→1,false→0(这个还算好记) -
empty string
''→0(这个也还算记得住) -
numeric string
'123'→123(这个还算好记)numeric string + alphabetic string
注:有一点不要混淆,使用'123abc'→NaN(这个还算好记)Number.parseInt或Number.parseFloat的话,它会自动过滤掉 alphabetic string'abc'的部分,所以不会返回NaN,这一点和强转 number 是不同的。 -
undefined→NaN,而null→0(这个不好记,为什么它俩会不一致呢🤔?)
object 转 number
它比较复杂,有三个步骤:
valueOf → toString → Number(value)
先用 object.valueOf 获取 value
如果这个 value 是一个对象(注:array, function 也算对象哦),那就再用 object.toString 获取 value。
如果 value 还是一个对象,那就报错。
只要 valueOf 或 toString 返回的 value 不是对象,那么就 Number(value)。
console.log(+{ valueOf: () => '5', toString : () => '10' }); // 5
console.log(+{ valueOf: {}, toString: () => '10' }); // 10
转 string
String(value) 可以把 value 强制转换成 string。
转换规则是:
-
123→'123' -
true→'true' -
undefined→'undefned' -
null→'null'
都挺好记的。
object 转 string
toString→ valueOf→ String(value)
和 object to number 一样,只是顺序不同,它是先调用 toString,如果返回的是对象,那就再调用 valueOf。
只要 toString 或 valueOf 返回的 value 不是对象,那么就 String(value)。
自动类型转换
if (value) 会把 value 强转成 boolean
!!value 会把 value 强转成 boolean
+value 会把 value 强转成 number
'string' + value 加号会把 value 强转成 string。比如:'123' + 3 → '1233'
value -*/ value 减乘除号会把 value 强转成 number。比如:'123' - '3' → 120
value == value 双等号在对比时,会先自动转换类型(规则下面会详细讲)。
双等号 ==
双等号在对比时,会先自动转换类型,它的规则蛮多的:
-
null和undefned是相等的 -
null和undefined对比前不会被转换类型 -
NaN和谁都不相等,包括NaN,也就是说NaN == NaN是false,NaN != NaN是true。 -
string == string、number == number、boolean == boolean、object == object类型相同就不会自动转换。 -
类型不同的情况下,比如
string == number、boolean == string、object == number,会先把它们转换成number,像这样Number(string) == Number(boolean)。注:不要问我为什么会转成
number,我也不清楚,总是这就是它的规则。![]()
我日常会用的类型转换
由于类型转换的规则很复杂,所以尽量还是少用为妙,以下是我常用的几个:
-
+(new Date())把date转成number,等价于(new Date()).getTime(),会得到 epoch time(从 1970 年 1 月 1 日到现在的 milliseconds)。 -
用
0和1来表示boolean——0是false,1是true。 if (object | array)判断有value,如果是nullorundefined会被转成false。我只会用来判断
object | array,string或number我不会这样写,因为规则不好记。-
'abc' + 123把number拼接到string里。
就这么多,其它的规则不太好记,所以我会尽量避开它们的类型转换。
Auto-boxing 机制
7 个 primitive types 中,有 5 个是 object-like:
console.log(typeof ''); // 'string'
console.log(typeof 0); // 'number'
console.log(typeof true); // 'boolean'
console.log(typeof Symbol()); // 'symbol'
console.log(typeof 0n); // 'bigint'
除了 null 和 undefined。
什么是 "object-like"?
console.log('hello world'.substring(0, 5)); // 'hello'
'hello world' 是 string 不是对象,为什么它可以调用 .substring 方法?
这方法哪来的?
new String('hello world').substring(0, 5);
其实这个方法来自 class String。
当一个 string(e.g. 'hello world').substring 时,JavaScript 引擎会进行 "临时装箱",把它变成 new String('hello world').substring,这就叫 auto-boxing 机制。
number → Number 和 boolean→ Boolean 也是如此。
symbol 和 bigint 则有一点特别。
Symbol 和 BigInt 不是 class,它们不可以 new Symbol、new BigInt。
因此,当我们访问 Symbol().description 时,它并不是 auto-boxing 成 new Symbol().description。
不过我们也不用分那么细,总之 JavaScript 引擎会特殊处理就是了(类似 auto-boxing 机制)。
结论:string、number、boolean、symbol、bigint 都不是对象,但是却可以访问属性和方法,这是因为 JavaScript 引擎做了特别处理,这个机制叫 auto-boxing。
什么时候会 auto-boxing?
除了 .property 和 .method 会 auto-boxing 以外,for...in 和 Object.getPrototypeOf 等也会
const number = 0;
console.log(Object.getPrototypeOf(number) === Number.prototype); // true
console.log(Object.keys('abc')); // ['0', '1', '2']
console.log(Object.getOwnPropertyNames('abc')); // ['0', '1', '2', 'length']
什么时候不会 auto-boxing?
console.log(typeof ''); // 'string'
console.log(typeof new String('')); // 'object'
console.log('' instanceof String); // false
console.log(new String('') instanceof String); // true
像 typeof 和 instanceof 就不会。
从这些例子中可以看到,并不是在每一种情况下都会 auto-boxing,因此我们在使用时一定要搞清楚状况。


浙公网安备 33010602011771号