JavaScript - Type
基本类型
JavaScript 的每一个
值都属于某一种数据类型
UndefinedNull- Boolean
- String
- Number
Symbol– ES6Object
Undefined + Null
Undefined
编程规范:使用
void 0代替undefined
- Undefined 代表
未定义,只有一个值undefinedundefined为全局变量,但并非关键字– 语言设计缺陷
- 任何变量在
赋值前的类型为是Undefined,值为undefined void运算可以将任意表达式变成undefined值
1 | console.log(void 0 === undefined) // true |
Null
Null 代表
定义了但为空,只有一个值null,null 是关键字
Boolean
Boolean 只有两个值,
true和false,且均为关键字
String
Unicode + UTF
- Unicode 为
字符集,每一个 Unicode 码点表示一个字符U+???- 基本字符区域(BMP):
U+0000 ~ U+FFFF
- UTF 为 Unicode 的
编码方式:规定码点在计算机中的表示方式,常见为UTF-8和UTF-16
String
- String 的最大长度为
2^53-1(编码长度) - String 为
值类型,永远无法变更 - String 把每个
UTF-16单元当作一个字符来处理 –From Java
Number
对应数学中的
有理数,但在计算机中,有一定的精度限制
NaN:占用特定数字Infinity:无穷大;-Infinity:负无穷大1/0==>Infinity1/-0==>-Infinity
- 浮点数存在
精度误差
1 | console.log(0.1 + 0.2 == 0.3) // false |
Symbol
ES6 引入,是一切
非字符串的对象Key的集合,整个对象系统被 Symbol 重塑
Symbol()函数前不能使用new,因为生成的 Symbol 是一个原始类型的值,不是对象Symbol值不是对象,所以也不能添加属性,类似于字符串的值类型
1 | let a1 = Symbol('A'); |
样例:使用
Symbol.iterator来定义for...of在对象上的行为
1 | let o = {} |
如果
Symbol的参数是一个对象,会调用该对象的toString()方法,将其转换为字符串,然后生成一个 Symbol 值
1 | const obj = { |
Symbol()函数的参数只是表示对当前 Symbol 值的描述,相同参数的 Symbol 函数的返回值是不相等的
1 | let s1 = Symbol(); |
Symbol 不能与其他类型的值进行运算
1 | let s = Symbol(); |
Symbol 可以显式转成
字符串
1 | let s = Symbol('A'); |
Symbol 可以转成
布尔值
1 | let s = Symbol('A'); |
Object
对象的定义为
属性的集合,属性分为数据属性和访问器属性,都是KV结构,Key可以为String或者Symbol
JavaScript 是
无法自定义类型的,『类』仅仅只是运行时对象的一个私有属性
Number、String和Boolean,这三个构造器是两用的
- 与
new搭配:产生对象直接调用:表示强制类型转换
1 | console.log(typeof 3) // number |
Symbol 如果与 new 搭配,会直接报错
1 | // console.log(typeof new Symbol('A')) // Uncaught TypeError: Symbol is not a constructor |
JavaScript 试图模糊
对象和基本类型之间的关系:可以在基本类型上使用对象的方法-装箱转换
1 | let s = 'abc' |
可以在原型上添加方法,并应用于基本类型
1 | Symbol.prototype.hello = () => console.log('hello js') |
根因:
.运算符提供了装箱操作,会根据基础类型构造一个临时对象,使得能在基础类型上调用对应对象的方法
类型转换
JavaScript 为
弱类型动态语言,发生类型转换非常频繁
==
语言设计缺陷:试图实现
跨类型的比较,规则非常复杂
最佳实践:进行
显式地类型转换后,再使用===进行比较
StringToNumber
大多数情况下,
Number是比parseInt和parseFloat更好的选择
1 | // 十进制、二进制、八进制、十六进制 |
parseInt默认只支持16 进制,且会忽略非数字字符,也不支持科学计数法
1 | console.log(parseInt('0xFF')) // 255 |
parseFloat直接把字符串作为十进制来解析,不会引入其它进制
1 | console.log(parseFloat('123.45')) // 123.45 |
NumberToString
当 Number 的绝对值较大或者较小的时候,将使用
科学计数法表示(保证产生的字符串不会过长)
1 | console.log(String(1e256)) // 1e+256 |
装箱转换
- 每一种基本类型
Number、String、Boolean、Symbol在对象中都有对应的类 - 装箱转换:将
基本类型转换为对应的对象 装箱机制会频繁产生临时对象,在高性能场景,应该尽量避免对基本类型做装箱转换
Symbol
1 | let s = (function () { |
通过内置的
Object函数,可以显式调用装箱能力
1 | let o = Object(Symbol('A')) |
每一类
装箱对象都有私有的Class属性,可以通过Object.prototype.toString来获取
在 JavaScript 中,无法更改私有的 Class 属性,比instanceof本身更准确call本身会产生装箱操作,需要配合typeof来区分基本类型还是对象类型
1 | let o = Object(Symbol('A')) |
拆箱转换
ToPrimitive:对象类型 -> 基础类型
对象到String和Number的转换:先拆箱再转换(对象 -> 基本类型 -> String/Number)
拆箱转换会尝试调用
valueOf和toString来获得拆箱后的基本类型
如果valueOf和toString都不存在,或者没有返回基本类型,会产生类型错误TypeError
valueOf -> toString
1 | let o = { |
toString -> valueOf
1 | let o = { |
在 ES6 之后,允许对象通过显式指定
@@toPrimitive Symbol来覆盖原有的拆箱行为
1 | let o = { |
typeof
同样为
语言的设计缺陷:typeof 的运算结果,与运行时数据类型有较多不一致的地方
| 示例表达式 | typeof 结果 | 运行时类型 |
|---|---|---|
null |
object |
Null |
(function(){}) |
function |
Object |
void 0 |
undefined |
Undefined |
Symbol("A") |
symbol |
Symbol |
| {} | object | Object |
| 3 | number | Number |
| “ok” | string | String |
| true | boolean | Boolean |












