mozilla

JavaScript 数据结构

编程语言都具有内建的数据结构,但各种编程语言的数据结构常有不同之处。本文试图列出 JavaScript 语言中内建的数据结构及其属性,它们可以用来构建其他的数据结构;同时尽可能的描述与其他语言的不同之处。

动态类型

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

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

数据类型

最新的 ECMAScript 标准定义了 7 种数据类型:

原始值

除 Object 以外的所有类型都是不可变的(值本身无法被改变)。例如,与 C 语言不同,JavaScript 中字符串是不可变的(译注:如,JavaScript 中对字符串的操作一定返回了一个新字符串,原始字符串并没有被改变)。我们称这些类型的值为“原始值”。

布尔类型

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

Null 类型

Null 类型只有一个值: null,更多详情可查看 nullNull

Undefined 类型

一个没有被赋值的变量会有个默认值 undefined,更多详情可查看 undefinedUndefined

数字类型

根据 ECMAScript 标准,JavaScript 中只有一种数字类型:基于 IEEE 754 标准的双精度 64 位二进制格式的值(-(253 -1) 到 253 -1)。它并没有为整数给出一种特定的类型。除了能够表示浮点数外,还有一些带符号的值:+Infinity-InfinityNaN (非数值,Not-a-Number)。

要检查值是否大于或小于 +/-Infinity,你可以使用常量 Number.MAX_VALUENumber.MIN_VALUE。另外在 ECMAScript 6 中,你也可以通过 Number.isSafeInteger() 方法还有 Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER 来检查值是否在双精度浮点数的取值范围内。 超出这个范围,JavaScript 中的数字不再安全了,也就是只有 second mathematical interger 可以在 JavaScript 数字类型中正确表现。

数字类型只有一个整数,它有两种表示方法: 0 可表示为 -0 和 +0("0" 是 +0 的简写)。 在实践中,这也几乎没有影响。 例如 +0 === -0 为真。 但是,你可能要注意除以0的时候:

> 42 / +0
Infinity
> 42 / -0
-Infinity

尽管一个数字常常仅代表它本身的值,但JavaScript提供了一些位运算符。 这些位运算符和一个单一数字通过位操作可以用来表现一些布尔值。但这通常被认为是一个不好的做法,虽然 JavaScript 不提供其他的方式来表示一组布尔值(如一个布尔值数组或一个布尔值分配给命名属性的对象)。位操作也容易使代码难以阅读,理解和维护, 在一些非常受限的情况下,可能需要用到这些技术,比如试图应付本地存储的存储限制。 位操作只应该是用来优化尺寸的最后选择。

字符串类型

JavaScript的字符串类型用于表示文本数据。它是一组16位的无符号整数值的“元素”。在字符串中的每个元素占据了字符串的位置。第一个元素的索引为0,下一个是索引1,依此类推。字符串的长度是它的元素的数量。

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

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

注意代码中的“字串符类型”!

可以使用字串符来表达复杂的数据。以下是一些很好的性质:

  • 容易连接构造复杂的字串符
  • 字串符容易被调试(你看到的往往在字串符里)
  • 字串符通常是许多APIs的常见标准 (input fields, local storage values, XMLHttpRequest当使用responseText等的时候回应) 而且他只能与字符串一同使用。

按照惯例, 字符串一般可以用来表达任何数据结构。这不是一个好主意。例如,使用一个分隔符,一个可以模仿一个列表(一个JavaScript的数组可能更适合一些) 。不幸的是,当一个分隔符在用于列表中的元素时,打乱了这个列表。 一个转义字符等。所有这些惯例都变成了一个不存在的维护负担而没有正确的工具使用。

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

符号类型

符号类型在ECMAScript 第6版中被引入Javascript. 符号类型是唯一的并且是不可修改的, 并且也可以用来作为Object的key的值(如下). 在某些语言当中也有类似的原子类型(Atoms). 你也可以认为为它们是C里面的枚举类型. 更多细节请看 Symbol 和 Symbol .

对象

在计算机科学中, 对象是指内存中的可以被 identifier引用的一块区域.

属性

在Javascript里,对象可以被看作是一个特性包。用对象字面量语法来定义一个变量或者对象,会自动初始化部分属性(也就是说,你定义一个var a = "Hello",那么a本身就会有a.substring这个方法,以及a.length这个属性,以及其它;如果你定义了一个对象,var a = {},那么a就会自动有a.hasOwnProperty及a.constructor等属性和方法。)这些属性和方法都可以被更改,包括其它复杂对象。

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

数据属性

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

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

访问器属性

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

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

"Normal" objects, and functions

A JavaScript object is a mapping between keys and values. Keys are strings and values can be anything. This makes objects a natural fit for hashmaps. However, one has to be careful about the non-standard __proto__ pseudo property. In environment that supports it, '__proto__' does not allow to manipulate one property with such a name, but the object prototype. In context where it is not necessarily known where the string comes from (like an input field), caution is required: other have been burned by this. In that case, an alternative is to use a proper StringMap abstraction.

Functions are regular objects with the additional capability of being callable.

数组

数组是以数字为下标并且拥有length属性的对象。此外,数组继承了 Array.prototype 的方法,比如indexOf(搜索某个值),push(往数组里追加值)。这种特性使得数组成为列表或者集合的最佳的存储结构(数据结构)。

日期

当你想要显示日期时,毋庸置疑,使用内建的 Date 对象

WeakMaps, Maps, Sets

Non-standard. Likely to be standardized as part of ECMAScript 6.

These data structures take object references as keys. A Set represents a set of objects, while WeakMaps and Maps associates a value to an object. The difference between Maps and WeakMaps is that in the former, object keys can be enumerated over. This allows garbage collection optimizations in the latter case.

One could implement Maps and Sets in pure ECMAScript 5. However, since objects cannot be compared (in the sense of "less than" for instance), look-up performance would necessarily be linear. Native implementations of them (including WeakMaps) can have look-up performance that is approximately logarithmic to constant time.

Usually, to bind data to a DOM node, one could set properties directly on the object or use data-* attributes. This has the downside that the data is available to any script running in the same context. Maps and WeakMaps make easy to privately bind data to an object.

TypedArrays

Non-standard. Likely to be standardized as part of ECMAScript 6.

See also

文档标签和贡献者

最后编辑者: JsonMe,
隐藏侧边栏