ECMAScript 6中的数组操作方法
本文介绍ECMAScript 6即将带给我们新的数组操作方法,以及在怎样在现有浏览器应用这些新的数组特性。
Note: 我将使用交替使用构造器(constructor)和类(class)两个术语。
类方法
数组(Array)自身所拥有的方法。
Array.from(arrayLike, mapFunc?, thisArg?)
Array.from()
的基本功能是,转换两种类型的对象成数组。
类数组对象(Array-like objects)
该类对象有长度与索引的属性。DOM操作符的结果即属于该类,如document.getElementsByClassName()
。
可迭代对象(Iterable objects)
这类对象在取值时,每次只能取一个元素。数组是可迭代的,就如ECMAScript中新的数组结构,映射(Map)和集(Set)。
以下代码是一个转换类数组对象到数组的一个示例:
let lis = document.querySelectorAll('ul.fancy li');
Array.from(lis).forEach(function (li) {
console.log(node);
});
querySelectorAll()
的结果不是一个数组,也不会有forEach()
这个方法。这是我们需要在使用这个方法之前,将它转换成数组的原因。
通过Array.from()使用Mapping
Array.from()
同样也是一个泛型使用map()
的替代选择。
let spans = document.querySelectorAll('span.name');
// map(), generically:
let names1 = Array.prototype.map.call(spans, s => s.textContent);
// Array.from():
let names2 = Array.from(spans, s => s.textContent);
两个方法中的第二个参数,都是箭头函数(arrow function)。
在这个示例中,document.querySelectorAll()
的结果又是一个类数组对象,而非数组。这就是我们不能直接调用map()
的原因。第一个示例中,为了使用forEach()
,我们将类数组对象转换成了数组。这里我们通过泛型方法和两个参数版本的Array.from()
,而省去了中间步骤。
Holes
Array.from()
会忽略数组里缺失的元素 - 洞(holes),它会以未定义的元素(undefined elements)进行对待。
> Array.from([0,,2])
[ 0, undefined, 2 ]
这就意味着,你可以使用Array.from()
来创建或者填充一个数组:
> Array.from(new Array(5), () => 'a')
[ 'a', 'a', 'a', 'a', 'a' ]
> Array.from(new Array(5), (x,i) => i)
[ 0, 1, 2, 3, 4 ]
如果你想用一个固定的值去填充一个数组,那么Array.prototype.fill()
(请看下文)将是一个更好的选择。第一个即是以上示例的两种方式。
在数组(Array)子类中的from()
另一个Array.from()
的使用场景是,转换类数组对象或可迭代对象到一个数组(Array)子类的一个实例。如你创建了一个Array的子类MyArray,想将此类对象转化成MyArray的一个实例,你就可以简单地使用MyArray.from()
。可以这样使用的原因是,在ECMAScript 6中构造器(constructors)会继承下去(父类构造器是它子类构造器的原型(prototype))。
class MyArray extends Array {
...
}
let instanceOfMyArray = MyArray.from(anIterable);
你可以将该功能与映射(mapping)结合起来,在一个你控制结果构造器的地方完成映射操作(map operation):
// from() – determine the result’s constructor via the receiver
// (in this case, MyArray)
let instanceOfMyArray = MyArray.from([1, 2, 3], x => x * x);
// map(): the result is always an instance of Array
let instanceOfArray = [1, 2, 3].map(x => x * x);
Array.of(...items)
如果你想将一组值转换成一个数组,你应该使用数组源文本(array literal)。特别是只有一个值且还是数字的时候,数组的构造器便罢工了。更多信息请参考。
> new Array(3, 11, 8)
[ 3, 11, 8 ]
> new Array(3)
[ , , ,]
> new Array(3.1)
RangeError: Invalid array length
便如果要将一组值转换成数字子构造器(sub-constructor)的一个实例,我们应该怎么做呢?这就是Array.of()
存在的价值(记住,数组子构造器会继承所有的数组方法,当然也包括of()
)。
class MyArray extends Array {
...
}
console.log(MyArray.of(3, 11, 8) instanceof MyArray); // true
console.log(MyArray.of(3).length === 1); // true
把值包裹嵌套在数组里,Array.of()
会相当方便,而不会有Array()
一样怪异的处理方式。但也要注意Array.prototype.map()
,此处有坑:
> ['a', 'b'].map(Array.of)
[ [ 'a', 0, [ 'a', 'b' ] ],
[ 'b', 1, [ 'a', 'b' ] ] ]
> ['a', 'b'].map(x => Array.of(x)) // better
[ [ 'a' ], [ 'b' ] ]
> ['a', 'b'].map(x => [x]) // best (in this case)
[ [ 'a' ], [ 'b' ] ]
如你所看,map()
会传递三个参数到它的回调里面。最后两个又是经常被忽略的(详细)。
原型方法(Prototype methods)
数组的实例会有很多新的方法可用。
数组里的迭代(Iterating over arrays)
以下的方法,会帮助完成在数组里的迭代:
Array.prototype.entries()
Array.prototype.keys()
Array.prototype.values()
以上的每一个方法都会返回一串值,却不会作为一个数组返回。它们会通过迭代器,一个接一个的显示。让我们看一个示例(我将使用Array.from()将迭代器的内容放在数组中
):
> Array.from([ 'a', 'b' ].keys())
[ 0, 1 ]
> Array.from([ 'a', 'b' ].values())
[ 'a', 'b' ]
> Array.from([ 'a', 'b' ].entries())
[ [ 0, 'a' ],
[ 1, 'b' ] ]
你可以结合entries()
和ECMAScript 6中的for-of
循环,方便地将迭代对象拆解成key-value对:
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
Note: 这段代码已经可以在最新的Firefox浏览器里运行了。t Firefox.
查找数组元素
Array.prototype.find(predicate, thisArg?)
会返回满足回调函数的第一个元素。如果没有任何一个元素满足条件,它会返回undefined
。比如:
> [6, -5, 8].find(x => x < 0)
-5
> [6, 5, 8].find(x => x < 0)
undefined
Array.prototype.findIndex(predicate, thisArg?)
会返回满足回调函数的第一个元素的索引。如果找不任何满足的元素,则返回-1。比如:
> [6, -5, 8].findIndex(x => x < 0)
1
> [6, 5, 8].findIndex(x => x < 0)
-1
两个find*方法都会忽略洞(holes),即不会关注undefined的元素。回调的完成函数签名是:
predicate(element, index, array)
通过findIndex()找NaN
Array.prototype.indexOf()
有一个大家所熟知的限制,那就是不能查找NaN。因为它用恒等(===)查找匹配元素:
> [NaN].indexOf(NaN)
-1
使用findIndex()
,你就可以使用Object.is()
,这就不会产生这样的问题:
> [NaN].findIndex(y => Object.is(NaN, y))
0
你同样也可以采用更通用的方式,创建一个帮助函数elemIs()
:
> function elemIs(x) { return Object.is.bind(Object, x) }
> [NaN].findIndex(elemIs(NaN))
0
Array.prototype.fill(value, start?, end?)
用所给的数值,填充一个数组:
> ['a', 'b', 'c'].fill(7)
[ 7, 7, 7 ]
洞(Holes)也不会有任何的特殊对待:
> new Array(3).fill(7)
[ 7, 7, 7 ]
你也可以限制你填充的起始与结束:
> ['a', 'b', 'c'].fill(7, 1, 2)
[ 'a', 7, 'c' ]
什么时候可以使用新的数组方法?
有一些方法已经可以在浏览器里使用了。通过,你可以通过kangax查看兼容性ECMAScript 6 compatibility table。
Paul Miller的 es6-shim库可以将ES6转换成ES5。
参考
- http://www.2ality.com/2014/05/es6-array-methods.html
- Holes in Arrays (Speaking JavaScript)
ECMAScript 6中的数组操作方法的更多相关文章
- ECMAScript 5中新增的数组方法
ECMAScript 5中定义了9个新的数组方法,用于遍历.映射.过滤.检测.简化和搜索数组. 在开始介绍之前,很有必要对这几个新增的数组方法做一个概述.首先,大多数方法的第一个参数接收一个函数,并且 ...
- JavaScript中的常用的数组操作方法
JavaScript中的常用的数组操作方法 一.concat() concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,仅会返回被连接数组的一个副本. var arr1 = [1,2 ...
- Dart 中常用的数组操作方法总结
这里总结了一些在 Dart 中常用的数组操作方法,以便查阅. 首先,我们准备两组数据,以方便后面使用: List<Map> students = [ { 'name': 'tom', 'a ...
- PHP中的常用数组操作方法
一.数组操作的基本函数 数组的键名和值array_values($arr); 获得数组的值array_keys($arr); 获得数组的键名array_flip($arr); 数组中的值与键名互 ...
- ECMASCRIPT 6中字符串的新特性
本文将覆盖在ECMAScript 6 (ES6)中,字符串的新特性. Unicode 码位(code point)转义 Unicode字符码位的长度是21位[2].而JavaScript的字符串,是1 ...
- JavaScript中的数组详解
JavaScript中的数组 一.数组的定义 数组是值的有序集合,或者说数组都是数据的有序列表. 二.创建数组 [字面量形式] 1.空数组 var arr=[]; 2.带有元素的数组 var arr= ...
- JavaScript中Array数组的方法
查找: indexOf.lastIndexOf 迭代:every.filter.forEach.map.somereduce.reduceRight 用法: /* 1 查找方法: * arr.inde ...
- JavaScript数据结构与算法(八) 集合(ECMAScript 6中定义的类似的Set类)
TypeScript方式实现源码 // 特性: // 1. 集合是由一组无序且唯一(即不能重复)的项组成的.这个数据结构使用了与有限集合相同的数学概念,但应用在计算机科学的数据结构中. // 2. 也 ...
- 数组操作方法(包括es5)
//push(); 定义:可以可向数组的末尾添加一个或更多元素,并返回新的长度. 方法:push(); 语法:数组.push(新元素1,新元素2,....,新元素x) 返回值:把指定的值添加到数组后的 ...
随机推荐
- hdu 1548 楼梯 bfs或最短路 dijkstra
http://acm.hdu.edu.cn/showproblem.php?pid=1548 Online Judge Online Exercise Online Teaching Online C ...
- PHP cURL模块
简介: cURL是利用URL语法在命令行方式下工作的文件传输工具,目前苹果机器已经内置了cURL.cURL是一个综合性的传输工具,对HTTP.FTP等协议提供了广泛的支持,它甚至可以实现迅雷.快车等下 ...
- 取消 virtualStore 注册表[启用和禁止 UAC虚拟化]
近日发现,在win2008R2 x64下运行的服务器程序,其注册表读取路径为: [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\SZDomain\itvc1] 但是经 ...
- centos下linux运行asp网站搭建配置-mono+nginx
一.首先安装一些需要的软件包 1. 首先更新CentOS上的软件包:yum –y update. 2. 安装一些需要的库: yum -y install gcc gcc-c++ bison pkg ...
- IOS适配
• Default.png(图片尺寸为320x480):显示在非Retina-3.5英寸屏幕上(iPhone3G\iPhone3GS,屏幕分辨率为320x480) • Default@2x.png(图 ...
- RPC 135端口
- Uploadify v3.2.1 上传图片并预览
前端JSP: <script type="text/javascript"> $(function() { $("#upload_org_code" ...
- LCLFramework框架之Repository模式
Respository模式在示例中的实际目的小结一下 Repository模式是架构模式,在设计架构时,才有参考价值: Repository模式主要是封装数据查询和存储逻辑: Repository模式 ...
- Akismet API 密钥(key)免费获取方法
Akismet插件是用户使用最广泛的垃圾评论插件,也是wordpress的创始人制作的,同时它也毫无疑问的成为wordpress的默认安装插件,这样的插件可以帮助用户解决垃圾评论的烦恼,而且也不用访客 ...
- ch6 影响 MySQLServer 性能的相关因素
第6章影响 MySQLServer 性能的相关因素 前言: 大部分人都一致认为一个数据库应用系统(这里的数据库应用系统概指所有使用数据库的系统)的性能瓶颈最容易出现在数据的操作方面,而数据库应用系统的 ...