Array - Prototype JavaScript 框架

Xunxin Prototype API

Array

Prototype 用许多功能强大的函数扩展了所有原生的 Javascript 数组。

主要通过以下两种方式:

  • 混入 Enumerable 模块,引入 Enumerable 固有的大量方法。
  • 另外增加了许多方法,在本节中有详细的论述。

在 Prototype 中,数组变得非常强大,不再是从前那个微不足道的对象,而我们对它的操作,也不再局限于 length 属性和 [] 索引操作符。使用新的操作方式,对于 99% 的常见应用,都能显著地简化代码。

为什么你将会停止使用 forin 来进行迭代(或许会永远跟它说 bye-bye 了)

许多 Javascript 开发人页都曾错误的使用过 forin 结构来迭代数组元素,这种类型的代码在 Prototype 中将不会工作。

你可以查看 ECMA 262 标准,它定义了 ECMAScript 第三版,据称所有主流浏览器都实现了该标准,甚至包括 MSIE。它为 Array(§15.4.4) 定义了许多方法,包括一些比较受欢迎的,如 concatjoinpoppush 等,已命名的函数有十个,但只对少数几个作了专门的描述。

在这份标准中,明确定义了 forin 结构(§12.6.4)的应用范围:枚举出现在关键字 in 右方的对象的属性。只有当属性被专门标记为不可枚举时才会在迭代中被忽略。数组的 prototypelength 属性已被预设为不可枚举,以防止使用 forin 时枚举到数组的方法。这导致开发人员使用 forin 作为遍历的快捷手段,而掩盖了 forin 的真实用意。

然而,Prototype 并没有办法将增加到 Array.prototype 中的方法标记为不可枚举。因此在数组中使用 forin,对于 Prototype 而言,将会枚举到所有扩展方法,例如那些从 Enumerable 模块中接收到的方法以及 Prototype 放在 Array 命名空间中的方法(本节中详细描述)。

开发人员该怎么做?

你可以使用索引进行遍历

for (var index = 0; index < myArray.length; ++index) {
	var item = myArray[index]; 
	// 你的代码... 
} 

或者使用迭代器(iterators),例如 each

myArray.each(function(item) {
	// 你的代码... 
}); 

Prototype 为使 forin 的使用回归其真实意图而采取的强制措施所造成的副作用不再成为一个负担: 正如你所看到的,几乎所有的数组遍历都能够通过 Array 提供的新方法或混入 Enumerable 引入的方法更便捷的实现。因此,手动遍历将会非常罕见。

性能关注

如果你有一个非常大的数组,在迭代时使用语法闭包(传递到迭代器的匿名函数,在每次循环时都会被调用),例如 each,或者使用需要对数组进行遍历的函数(如 uniq),可能性能会不尽如人意。若发生这种情况,最好用数字索引手动构造循环, 但是要注意对 length 属性的缓存,并小心使用前缀 ++ 操作符。

//通常在循环时需要缓存长度属性:这样在完全遍历大数组时具有较好的性能
for (var index = 0, len = myArray.length; index < len; ++index) {
	var item = myArray[index];
	// 你的代码...
} 

译注:为什么要缓存长度属性?在静态编译语言的 for 语句中,使用 index < myArray.length 作为条件判断并无不妥,因为通常编译器会对这种类型的语句进行优化,自动缓存长度属性,但 Javascript 作为一种动态解释型语言, 并不会自动缓存长度属性,而是每次循环完成后进行条件判断时再调用相关的属性方法求取长度,这样必须会导致性能的下降。

方法

clear

clear() -> Array

清空所有数组元素。

clone

clone() -> newArray

在不损害原始数组的前提下,返回一个数组的复本。

compact

compact() -> newArray

返回一个不包含 null/undefined 值元素的数组的新版本。

each

each(iterator) -> Array

按照数字索引升序遍历数组。

first

first() -> value

返回数组中第一个元素,若数组为空,返回 undefined

flatten

flatten() -> newArray

返回一个不具有嵌套层次结构的数组,内嵌的数组递归加入到最外层数组中。当处理递归集合算法时,这个方法被证明是非常有用的。

from

Array.from(iterable) -> actualArray

克隆一个已有的数组或者根据一个类似于数组的集合创建新的数组。

$A() 工具函数的另一个称谓。完整的描述和样例请参照 $A 的文档。

indexOf

indexOf(value) -> position

返回数组中与参数匹配的第一个元素的位置,如果不存在匹配的元素,返回 -1

inspect

inspect() -> String

返回一个数组的字符串表示形式,用于调试。
译注:该方法返回一个类似于创建数组的代码的字符串表现形式。如 "['a', ['b', [Object Object]], 'c']",更详细的信息请参阅代码。

last

last() -> value

返回数组中最后一个元素,若数组为空,返回 undefined

reduce

reduce() -> Array | singleValue

简化数组:只具有一个元素的数组被转换为那个唯一的元素,包含多个元素的数组返回其本身。

reverse

reverse([inline = true]) -> Array

返回数组的逆序版本,默认情形下,直接在原始数组内部进行序列调整,如果 inline 设置为 false,则首先克隆原始数组,然后在克隆版本中进行调整。

size

size() -> Number

返回数组的元素个数。

toArray

toArray() -> newArray

这个方法针对因混入 Enumerable 而引入的 toArray 方法进行了本地优化。

toJSON
1.5.1

toJSON() -> String

返回一个 JSON 字符串。

uniq

uniq() -> newArray

返回去除数组重复元素后的版本。如果没有重复的元素,返回原始数组本身。

without

without(value...) -> newArray

返回不包括参数中任意一个指定值的数组版本。(即返回的数组中不包括任何一个参数中指定的值)