Array
Prototype 用许多功能强大的函数扩展了所有原生的 Javascript 数组。
主要通过以下两种方式:
-
混入 Enumerable 模块,引入
Enumerable
固有的大量方法。 - 另外增加了许多方法,在本节中有详细的论述。
在 Prototype 中,数组变得非常强大,不再是从前那个微不足道的对象,而我们对它的操作,也不再局限于 length
属性和
[]
索引操作符。使用新的操作方式,对于 99% 的常见应用,都能显著地简化代码。
为什么你将会停止使用 for
…in
来进行迭代(或许会永远跟它说 bye-bye 了)
许多 Javascript 开发人页都曾错误的使用过 for
…in
结构来迭代数组元素,这种类型的代码在
Prototype 中将不会工作。
你可以查看 ECMA 262 标准,它定义了
ECMAScript 第三版,据称所有主流浏览器都实现了该标准,甚至包括 MSIE。它为 Array
(§15.4.4)
定义了许多方法,包括一些比较受欢迎的,如 concat
、join
、pop
、push
等,已命名的函数有十个,但只对少数几个作了专门的描述。
在这份标准中,明确定义了 for
…in
结构(§12.6.4)的应用范围:枚举出现在关键字 in
右方的对象的属性。只有当属性被专门标记为不可枚举时才会在迭代中被忽略。数组的 prototype
和 length
属性已被预设为不可枚举,以防止使用 for
…in
时枚举到数组的方法。这导致开发人员使用
for
…in
作为遍历的快捷手段,而掩盖了 for
…in
的真实用意。
然而,Prototype 并没有办法将增加到 Array.prototype
中的方法标记为不可枚举。因此在数组中使用
for
…in
,对于 Prototype 而言,将会枚举到所有扩展方法,例如那些从
Enumerable 模块中接收到的方法以及 Prototype 放在 Array
命名空间中的方法(本节中详细描述)。
开发人员该怎么做?
你可以使用索引进行遍历
for (var index = 0; index < myArray.length; ++index) {
var item = myArray[index];
// 你的代码...
}
或者使用迭代器(iterators),例如 each:
myArray.each(function(item) {
// 你的代码...
});
Prototype 为使 for
…in
的使用回归其真实意图而采取的强制措施所造成的副作用不再成为一个负担:
正如你所看到的,几乎所有的数组遍历都能够通过 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
方法进行了本地优化。
toJSON1.5.1
toJSON() -> String
返回一个 JSON 字符串。
uniq
uniq() -> newArray
返回去除数组重复元素后的版本。如果没有重复的元素,返回原始数组本身。
without
without(value...) -> newArray
返回不包括参数中任意一个指定值的数组版本。(即返回的数组中不包括任何一个参数中指定的值)