winter老师的重学前端真的是一门很好的课程,看了第一课,收获颇多,填了很多Js类型的坑,总结如下。

基础类型

  1. Undefined
  2. Null
  3. Boolean
  4. String
  5. Number
  6. Symbol
  7. Object

boolean这个类型比较简单,不单独作解释。Symbol这个类型太复杂,后面单独总结。

Undefined 和 Null

  • undefined并不是一个关键字。我们日常访问的undefined其实是访问的global级别的undefined变量,undefined变量的值是基础类型undefined。但是在现代浏览器中,undefined都不能被覆写。
  • undefined代表一个变量初始化了但是没有赋值,任何变量初始化前值都是undefined。
  • null是JavaScript的关键字,表示的是一个空值。
  • 所有变量定义都不要赋undefined值,这样会让代码难以理解(到底是代码没有赋值还是?)

String

  • string的最大长度是2^53-1,但是长度并不是指代字符数,而是字符串的UTF16编码的和,比如需要计算一个emoji的长度,你会发现是2。
  • 字符串方法比如length和charAt都是基于字符串编码和的。
  • 字符串一旦构造便不可更改,属于值类型。

Number

  • Js中除开规定有理数,还规定了NaN,Infinity,-Infinity
  • Js中有+0和-0,在加减法中没有问题,在乘除法中,如果是 x * -0 会得到 -0,x/-0 会得到 -Infinity。
  • Js中的Number类型范围是-2^53-2^53,如果不使用BigInt,只能表示这个范围之内的整数
  • 非整数类型的Number无法使用 == 或者===来进行比较,0.2 + 0.1 == = 0.3 会返回false,如果想要得到正确的匹配结果,请使用 Math.abs(0.1 + 0.2 -0.3) <= Number.EPSILON

Object

  • Js中对象是属性的集合。属性分为数据属性和访问器属性,以key-value结构进行存储,key可以是字符串或者是个Symbol类型。
  • Js中的类和Java中的类有一些不同,Java中的类代表的是真正的类型,但是Js中的类只是运行时对象的一个私有属性。
  • Number/String/Boolean和Symbol这四个基本类型都自带对应的构造器,如果使用 new 操作符,会返回一个对象类型而不是基本类型。
  • Js中的基本类型和对象的边界很模糊,可以直接在基础类型上调用方法,比如"abc".charAt(0),也可以通过给原型添加方法给基础类型增加方法。
  • 为什么基础类型可以调用对象方法?本质上是 . 运算符提供了装箱操作,这个运算符会根据基础类型构造一个临时对象。

类型转换

值转换表如下

StringToNumber

String到Number的类型转换支持十进制/二进制/八进制和十六进制

  • 30
  • 0b111
  • 0o13
  • 0xFF

同时还支持科学计数法

  • 1e3
  • -1e-2

和parseInt和parseFloat相比,

  • 不传入第二个参数的情况下,parseInt只支持16进制前缀,同时不支持科学计数法。在一些老浏览器中parseInt甚至会把0开头的字符串当做8进制进行转换。
  • parseFloat只会把字符串当做十进制数进行转换。
  • 多数情况下,Number比parseInt和parseFloat更优。

NumberToString

两种情况,当number

  • 值较小时,采用十进制转换
  • 值较大时,采用科学计数法表示

装箱操作

把基本类型转换为对应的对象称作装箱操作

由于Symbol无法使用new操作符,如果想要声明一个Symbol对象,可以这么做。

1
var symbolObject = (function() {return this;}).call(Symbal("a"));

装箱对象有internal slot,这个internal slot是在Object被创建时动态生成的,并且生成后不可被改变。因此,可以使用如下代码获取数据的准确类型。

1
2
var symbolObject = Object(Symbol("a"));
Object.prototype.toString.call(symbolObject); // [object Symbol]

拆箱转换

在标准中定义了toPrimitive,这个操作能把对象类型转换到基本类型,这个操作即拆箱转换。

在拆箱转换中,会尝试调用valueOf和toString来获得基本类型,如果两个方法都不存在,或者没有返回基本类型,就会产生TypeError。

需要注意的是,在对String类型进行拆箱时,会先调用toString,其余情况会先调用valueOf。

在ES6之后,允许显示指定Symbol.toPrimitive来覆盖默认的toPrimitive行为。该行为会覆盖默认的toString和valueOf判断。