跳至主要內容

类型

Mr.LRH大约 6 分钟

类型

JavaScript语言的每一个值都属于某一种数据类型。JavaScript语言规定了7种语言类型。语言类型广泛用于变量、函数参数、表达式、函数返回值等场合。

Undefined

Q&A

Q:为什么有的编程规范要求用 void 0 代替 undefined

Undefined 类型表示未定义,它的类型只有一个值,就是 undefined。

任何变量在赋值前是 Undefined 类型,值为 undefined。一般用全局变量 undefined 来表达这个值,或者 void 运算来把任一一个表达式变成 undefined 值。

因为 JavaScript 的代码 undefined 是一个变量,而并非是一个关键字,所以,为了避免无意中被篡改,建议使用 void 0 来获取undefined值。

Null

null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。

Boolean

Boolean 类型有两个值, true 和 false,它用于表示逻辑意义上的真和假。

String

String 有最大长度是 2^53 - 1。

String 是字符串的 UTF16 编码,字符串的操作 charAt、charCodeAt、length 等方法针对的都是 UTF16 编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。

JavaScript 字符串把每个 UTF16 单元当作一个字符来处理,所以处理非BMP(超出 U+0000 - U+FFFF 范围)的字符时,应该格外小心。

Number

Number类型有 18437736874454810627(即264-253+3) 个值。

Number 类型基本符合 IEEE 754-2008 规定的双精度浮点数规则,但是JavaScript为了表达几个额外的语言场景,规定了几个例外的情况:

  • NaN,占用了 9007199254740990,这原本是符合IEEE规则的数字;
  • Infinity,无穷大;
  • -Infinity,负无穷大。

JavaScript 中有 +0 和 -0 ,除法的场合需要特别留意区分,区分 +0 和 -0 的方式,正是检测 1/x 是 Infinity 还是 -Infinity

根据双精度浮点数的定义,Number类型中有效的整数范围是-0x1fffffffffffff至0x1fffffffffffff,所以 Number 无法精确表示此范围外的整数。

根据浮点数的定义,非整数的Number类型无法用 ==(===也不行) 来比较。

Q&A

为什么在JavaScript中,0.1+0.2 != 0.3

浮点数运算的精度问题导致等式左右的结果并不是严格相等,而是相差了个微小的值。实际上,这里错误的不是结论,而是比较的方法,正确的比较方法是使用 JavaScript 提供的最小精度值:Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON

Symbol

Symbol 是一切非字符串的对象key的集合。具有字符串类型的描述,但是即使描述相同,Symbol也不相等。

Object

JavaScript中的几个基本类型,都在对象类型中有一个“亲戚”,分别是 Number、String、Boolean、Symbool。Number、String和Boolean,三个构造器是两用的,当跟 new 搭配时,它们产生对象,当直接调用时,它们表示强制类型转换。

注意:3 与 new Number(3) 是完全不同的值,一个是 Number 类型, 一个是对象类型。

JavaScript对象的两类属性

  • 数据属性
    • value:属性的值
    • writable:决定属性能否被赋值
    • enumerable:决定for in能否枚举该属性
    • configurable:决定该属性能否被删除或者改变特征值
  • 访问器(getter/setter)属性
    • getter:函数或undefined,在取属性值时被调用
    • setter:函数或undefined,在设置属性值时被调用
    • enumerable:决定for in能否枚举该属性
    • configurable:决定该属性能否被删除或者改变特征值

用于定义属性的代码会产生数据属性,其中的writable、enumerable、configurable都默认为true。数据属性可使用内置函数 Object.getOwnPropertyDescripter来查看,要想改变属性的特征,或者定义访问器属性,我们可以使用 Object.defineProperty

访问器属性使得属性在读和写时执行代码,它允许使用者在写和读属性时,得到完全不同的值。在创建对象时,也可以使用 get 和 set 关键字来创建访问器属性

JavaScript中的对象分类

  • 宿主对象(host Objects):由JavaScript宿主环境提供的对象,它们的行为完全由宿主环境决定。
  • 内置对象(Built-in Objects):由JavaScript语言提供的对象。
    • 固有对象(Intrinsic Objects ):由标准规定,随着JavaScript运行时创建而自动创建的对象实例。
    • 原生对象(Native Objects):可以由用户通过Array、RegExp等内置构造器或者特殊语法创建的对 象。
    • 普通对象(Ordinary Objects):由{}语法、Object构造器或者class关键字定义类创建的对象,它能够 被原型继承。

Q&A

Q: 为什么给对象添加的方法能用在基本类型上

A:运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得能在基础类型上调用对应对象的方法。

类型转换

StringToNumber

字符串到数字的类型转换,存在一个语法结构,类型转换支持十进制、二进制、八进制和十六进制,,JavaScript支持的字符串语法还包括正负号科学计数法

在任何环境下,都建议传入 parseInt 的第二个参数,而 parseFloat 则直接把原字符串作为十进制来解析,它不会引入任何的其他进制。多数情况下,Number 是比 parseInt 和parseFloat 更好的选择。

NumberToString

当Number绝对值较大或者较小时,字符串表示则是使用科学计数法表示的。

装箱转换

每一种基本类型Number、String、Boolean、Symbol在对象中都有对应的类,所谓【装箱转换】,正是把基本类型转换为对应的对象,它是类型转换中一种相当重要的种类。

每一类装箱对象皆有私有的 Class 属性,这些属性可以用 Object.prototype.toString 获取在 JavaScript 中,没有任何方法可以更改私有的 Class 属性,因 Object.prototype.toString 是可以准确识别对象对应的基本类型的方法,它比 instanceof 更加准确。注意,call 本身会产生装箱操作,所以需要配合 typeof 来区分基本类型还是对象类型。

拆箱转换

在JavaScript标准中,规定了 ToPrimitive 函数,它是对象类型到基本类型的转换(即,拆箱转换)。在 ES6 之后,还允许对象通过显式指定 @@toPrimitive Symbol 来覆盖原有的行为。

对象到 String 和 Number 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,再从基本类型转换为对应的 String 或者 Number。

拆箱转换会尝试调用 valueOf 和 toString 来获得拆箱后的基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,则会产生类型错误 TypeError。

规范类型

  • List 和 Record:用于描述函数传参过程
  • Set:主要用于解释字符集等
  • Completion Record:用于描述异常、跳出等语句执行过程
  • Reference:用于描述对象属性访问、delete等
  • Property Descriptor:用于描述对象的属性
  • Lexical Environment 和 Environment Record:用于描述变量和作用域
  • Data Block:用于描述二进制数据
上次编辑于:
贡献者: lrh21g