JavaScript - Type
基本类型
JavaScript 的每一个
值都属于某一种数据类型
- Undefined
- Null
- Boolean
- String
- Number
- Symbol– ES6
- Object
Undefined + Null
Undefined
编程规范:使用
void 0代替undefined
- Undefined 代表未定义,只有一个值undefined- undefined为- 全局变量,但- 并非关键字– 语言设计- 缺陷
 
- 任何变量在赋值前的类型为是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==>- Infinity
- 1/-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 | 












