数据类型和数据结构

动态类型

JavaScript 是一种弱类型或者说动态语言。这意味着你不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。这也意味着你可以使用同一个变量保存不同类型的数据:

1
2
3
var foo = 42;    // foo is a Number now
foo = "bar"; // foo is a String now
foo = true; // foo is a Boolean now

数据类型

ECMAScript 标准定义了 8 种数据类型:

  • 7 种原始类型,使用typeof运算符检查:

    • undefinedtypeof instance === "undefined"
    • Booleantypeof instance === "boolean"
    • Numbertypeof instance === "number"
    • Stringtypeof instance === "string
    • BigInttypeof instance === "bigint"
    • Symboltypeof instance === "symbol"
    • nulltypeof instance === "object"
  • Objecttypeof instance === "object"

Object是任何 constructed 对象实例的特殊非数据结构类型,也用做数据结构:new Object,new Array,new Map,new Set,new WeakMap,new WeakSet,new Date,和几乎所有通过 new keyword 创建的东西。

typeof 操作符的唯一目的就是检查数据类型,如果我们希望检查任何从 Object 派生出来的结构类型,使用 typeof 是不起作用的,因为总是会得到 "object"。检查 Object 种类的合适方式是使用 instanceof 关键字。但即使这样也存在误差。

原始值

除 Object 以外的所有类型都是不可变的(值本身无法被改变)。

例如,JavaScript 中字符串是不可变的,JavaScript 中对字符串的操作一定返回了一个新字符串,原始字符串并没有被改变。

我们称这些类型的值为“原始值”。

Boolean

布尔表示一个逻辑实体,可以有两个值:truefalse

Null

Null 类型只有一个值: null

Undefined

一个没有被赋值的变量会有个默认值 undefined

Number

JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(2^53 -1) 到 2^53 -1)

它并没有为整数给出一种特定的类型。除了能够表示浮点数外,还有一些带符号的值:+Infinity-InfinityNaN

要检查值是否大于或小于 +/-Infinity,可以使用常量 Number.MAX_VALUENumber.MIN_VALUE

也可以通过 Number.isSafeInteger() 方法还有 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER 来检查值是否在双精度浮点数的取值范围内。

数字类型中只有一个整数有两种表示方法: 0 可表示为 -0 和 +0(”0” 是 +0 的简写)。

1
2
42 / +0; // Infinity
42 / -0; // -Infinity

BigInt

BigInt类型是 JavaScript 中的一个基础的数值类型,可以用任意精度表示整数。

使用BigInt,您可以安全地存储和操作大整数,甚至可以超过数字的安全整数限制。BigInt是通过在整数末尾附加 n 或调用构造函数来创建的。

可以对BigInt使用运算符+*-**%,就像对数字一样。BigInt 严格来说并不等于一个数字,但它是松散的。

BigInt不能与数字互换操作。否则,将抛出TypeError

String

JavaScript 的字符串类型用于表示文本数据。

它是一组16位的无符号整数值的“元素”。在字符串中的每个元素占据了字符串的位置。

第一个元素的索引为 0,下一个是索引 1,依此类推。字符串的长度是它的元素的数量。

不同于类 C 语言,JavaScript 字符串是不可更改的。这意味着字符串一旦被创建,就不能被修改。但是,可以基于对原始字符串的操作来创建新的字符串。

  • 获取一个字符串的子串可通过选择个别字母或者使用 String.substr()
  • 两个字符串的连接使用连接操作符 (+) 或者 String.concat()

表达文本数据和符号数据时候推荐使用字符串。当表达复杂的数据时,使用字符串解析和适当的缩写。

Symbol

符号(Symbols)是 ECMAScript 第6版新定义的。符号类型是唯一且不可修改的, 并且可以用来当作为 Object 的 key 的值

对象

对象是指内存中的可以被 标识符引用的一块区域。

属性

在 JavaScript 里,对象可以被看作是一组属性的集合。用 对象字面量语法 来定义一个对象时,会自动初始化一组属性。(也就是说,你定义一个var a = "Hello",那么a本身就会有a.substring这个方法,以及a.length这个属性,以及其它;如果你定义了一个对象,var a = {},那么 a 就会自动有a.hasOwnPropertya.constructor等属性和方法。)而后,这些属性还可以被增减。属性的值可以是任意类型,包括具有复杂数据结构的对象。属性使用键来标识,它的键值可以是一个字符串或者符号值(Symbol)。

ECMAScript 定义的对象中有两种属性:数据属性和访问器属性。

数据属性

数据属性是键值对,并且每个数据属性拥有下列特性:

特性 数据类型 描述 默认值
[[Value]] 任何JS类型 包含这个属性的数据值。 undefined
[[Writable]] Boolean 如果该值为 false,则该属性的 [[Value]] 特性 不能被改变。 false
[[Enumerable]] Boolean 如果该值为 true,则该属性可以用 for…in 循环来枚举。 false
[[Configurable]] Boolean 如果该值为 false,则该属性不能被删除,
并且除了 [[Value]] 和 [[Writable]] 以外的特性都不能被改变。
false

访问器属性

访问器属性有一个或两个访问器函数 (get 和 set) 来存取数值,并且有以下特性:

特性 类型 描述 默认值
[[Get]] 函数对象或者 undefined 该函数使用一个空的参数列表,能够在有权访问的情况下读取属性值。另见 get。 undefined
[[Set]] 函数对象或者 undefined 该函数有一个参数,用来写入属性值,另见 set。 undefined
[[Enumerable]] Boolean 如果该值为 true,则该属性可以用 for…in 循环来枚举。 false
[[Configurable]] Boolean 如果该值为 false,则该属性不能被删除,并且不能被转变成一个数据属性。 false