JavaScript学习笔记之ES6数组方法


Posted in Javascript onMarch 25, 2016

ES6(ECMAScript 6)是即将到来的新版本JavaScript语言的标准,代号harmony(和谐之意,显然没有跟上我国的步伐,我们已经进入中国梦版本了)。上一次标准的制订还是2009年出台的ES5。目前ES6的标准化工作正在进行中,预计会在14年12月份放出正式敲定的版本。但大部分标准已经就绪,且各浏览器对ES6的支持也正在实现中。

ES6给数组添加了一些新特性,而这些新特性到目前为止完全可以运用到自己的业务层。在这一节中将总结有关于ES6给数组提供一些新特性的使用方法。

ES6提供的两个静态方法:

Array.from

Array.of

ES6提供操作、填充和过滤数组的方法:

Array.prototype.copyWidthin
Array.prototype.fill
Array.prototype.find
Array.prototype.findIndex

ES6中有关于数组迭代的方法:

Array.prototype.keys
Array.prototype.values
Array.prototype.entries
Array.prototype[Symbol.iterator]

接下来主要看看这些方法的使用。

Array.from()

Array.from()方法主要用于将两类对象(类似数组的对象[array-like object]和可遍历对象[iterable])转为真正的数组。

在ES5中常常使用下面这样的方法将一个类似数组的对象转换成一个数组:

function cast () {
return Array.prototype.slice.call(arguments);
}
cast('a','b','c','d'); // ["a", "b", "c", "d"]

或者你也可以写成:

function cast () {
return [].slice.call(arguments);
}
cast('a','b','c','d'); // ["a", "b", "c", "d"]

在ES6中可以使用Array.from将一个类似数组的对象转换为一个真正的数组。

所谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象都是类似数组对象,都可以通过Array.from方法将其转换成一个真正的数组。

let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
}
console.log(Array.from(arrayLike)); // ["a","b","c"]

在ES6中,扩展运算符(...)也可以将某些数据结构转为数组。只不过它需要在背后调用遍历器接口Symbol.iterator。

function cast (){
return [...arguments]
}
cast('a','b','c'); // ["a","b","c"]

值得注意的是如果一个对象没有部署遍历器接口,使用扩展运算符是无法将类似数组对象转换成数组。

Array.from接受三个参数,但只有input是必须的:

input: 你想要转换的类似数组对象和可遍历对象

map: 类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

context: 绑定map中用到的this

只要是部署了iterator接口的数据结构,Array.from都能将其转为数组:

let arr = Array.from('w3cplus.com')
console.log(arr); // ["w","3","c","p","l","u","s",".","c","o","m"]
let namesSet = new Set(['a', 'b'])
let arr2 = Array.from(namesSet) 
console.log(arr2); //["a","b"]

上面的代码,因为字符吕和Set结构都具有iterator接口,因此可以被Array.from转为真正的数组。如果参数是一个真正的数组,Array.from也会返回一个一模一样的新数组:

let arr = Array.from([1, 2, 3]);
console.log(arr); // [1,2,3]

前面也说过Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,处理后的值放入返回的数组:

Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
Array.from([1, 2, 3], (x) => x * x)
// [1, 4, 9]

如果map函数里面用到了this关键字,还可以传入Array.from的第三个参数,用来绑定this。

Array.from()可以将各种值转为真正的数组,并且还提供map功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法。

Array.from({ length: 2 }, () => 'jack')
// ['jack', 'jack']

上面代码中,Array.from的第一个参数指定了第二个参数运行的次数。这种特性可以让该方法的用法变得非常灵活。

Array.from()的另一个应用是,将字符串转为数组,然后返回字符串的长度。因为它能正确处理各种Unicode字符,可以避免JavaScript将大于\uFFFF的Unicode字符,算作两个字符的bug。

function countSymbols(string) {
return Array.from(string).length;
}

使用Array.from()还可以返回各种数据类型:

function typesOf () {
return Array.from(arguments, value => typeof value)
}
typesOf(null, [], NaN)
// <- ['object', 'object', 'number']

你也可以使用map方法实现上面代码的功能:

function typesOf (...all) {
return all.map(value => typeof value)
}
typesOf(null, [], NaN)
// <- ['object', 'object', 'number']
Array.of

使用Array.of方法可以将一组值转换为数组。

Array.of = function of () {
return Array.prototype.slice.call(arguments)
}

但你不能使用Array.of来替代Array.prototype.slice.call,他们的行为不一样:

Array.prototype.slice.call([1, 2, 3])
// <- [1, 2, 3]
Array.of(1, 2, 3)
// <- [1, 2, 3]
Array.of(3)
// <- [1]

这个方法主要目的主要还是用来弥补数组构造函数Array()的不足,因为参数个数的不同,会导致Array()行为有所差异:

new Array()
// <- []
new Array(undefined)
// <- [undefined]
new Array(1)
// <- [undefined x 1]
new Array(3)
// <- [undefined x 3]
new Array(1, 2)
// <- [1, 2]
new Array(-1)
// <- RangeError: Invalid array length

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载,而且他们的行为非常统一:

Array.of()
// <- []
Array.of(undefined)
// <- [undefined]
Array.of(1)
// <- [1]
Array.of(3)
// <- [3]
Array.of(1, 2)
// <- [1, 2]
Array.of(-1)
// <- [-1]

Array.of方法可以使用下面的代码来模拟实现:

function ArrayOf(){
return [].slice.call(arguments);
}

copyWidthin

copyWidthin方法可以在当前数组内部,将指定位置的数组项复制到其他位置(会覆盖原数组项),然后返回当前数组。使用copyWidthin方法会修改当前数组。

Array.prototype.copyWithin(target, start = 0, end = this.length)

copyWidthin将会接受三个参数:

target: 这个参数是必须的,从该位置开始替换数组项

start: 这是一个可选参数,从该位置开始读取数组项,默认为0,如果为负值,表示从数组的右边向左开始读取

end: 这是一个可选参数,到该位置停止读取的数组项,默认等于Array.length。如果为负值,表示倒数

我们先来看一个简单的示例,下面声明了一个items数组:

var items = [1, 2, 3, ,,,,,,,]; // <- [1, 2, 3, undefined x 7]

下面的代码将在数组items的第六个位置开始粘贴数组项。粘贴过去的数组项是从items的第二位开始到第三位置结束。

items.copyWithin(6, 1, 3)
// <- [1, 2, 3, undefined × 3, 2, 3, undefined × 2]

下面是更多例子:

// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]
// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5}
// 将2号位到数组结束,复制到0号位
var i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]
// 对于没有部署TypedArray的copyWithin方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]
Array.prototype.fill

Array.prototype.fill方法使用给定的值填充一个数组:

['a', 'b', 'c'].fill(0)
// <- [0, 0, 0]
new Array(3).fill(0)
// <- [0, 0, 0]

上面这种方法用于空数组的初始化非常方便。数组中已有的元素会全部被抹去。

除此之外,Array.prototype.fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

['a', 'b', 'c',,,].fill(0, 2)
// <- ['a', 'b', 0, 0, 0]
new Array(5).fill(0, 0, 3)
// <- [0, 0, 0, undefined x 2]

Array.prototype.fill提供的值可以是任意的,不仅可以是一个数值,甚至还可以是一个原始类型:

new Array(3).fill({})
// <- [{}, {}, {}]

不过这个方法不可以接受数组的映射方法,不过可以接受一个索引参数或类似下面这样的方式:

new Array(3).fill(function foo () {})
// <- [function foo () {}, function foo () {}, function foo () {}]
Array.prototype.find

Array.prototype.find方法用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的数组项,然后返回该数组项。如果没有符合条件的数组项,则返回undefined。

[1, 2, 3, 4, 5].find(item => item > 2)
// <- 3
[1, 2, 3, 4, 5].find((item, i) => i === 3)
// <- 4
[1, 2, 3, 4, 5].find(item => item === Infinity)
// <- undefined

另外这种方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原始数组。

[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
Array.prototype.findIndex

这个方法类似于.some和.find方法。像.some返回true;像.find返回item。如果array[index] === item则返回其index。

Array.prototype.findIndex方法主要是用来返回数组项在数组中的位置。其和Array.prototype.find方法非常类似,接受一个回调函数,如果符合回调函数的条件,则返回数组项在数组中的位置,如果所有数组项都不符合回调函数条件,则会返回-1。

[1, 2, 3, 4, 5].find(item => item > 2)
// <- 2
[1, 2, 3, 4, 5].find((item, i) => i === 3)
// <- 3
[1, 2, 3, 4, 5].find(item => item === Infinity)
// <- -1

这个方法也可以接受第二个参数,用来绑定回调函数的this对象。

注:Array.prototype.find和Array.prototype.findIndex两个方法都可以发现NaN,弥补数组的indexOf方法的不足。

[NaN].indexOf(NaN)
// -1
[NaN].findIndex(y => Object.is(NaN, y))
// 0

上面的代码中,indexOf方法无法识别数组的NaN成员,但是findIndex方法可以借助Object.is方法做到。

ES6遍历数组的方法

ES6提供了三个新方法:entries()、keys()和values(),用来遍历数组。它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对数组的键名的遍历、values()是对数组键值的遍历,entries()方法是对数值的键值对的遍历。

for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 'a'
// 'b'
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"

如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历:

let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']

总结

这里简单的总结了有关于ES6中数组的相关方法。说实在的,初次接触ES6,很多东西都看得云里来雾里去。这里只是整理了一下这方面的相关知识。

关于JavaScript学习笔记之ES6数组方法小编就给大家介绍到这里,希望对大家有所帮助!

Javascript 相关文章推荐
js 得到文件后缀(通过正则实现)
Jul 08 Javascript
js 文本滚动效果的实例代码
Aug 17 Javascript
验证控件与Button的OnClientClick事件详细解析
Dec 04 Javascript
浅谈javascript对象模型和function对象
Dec 26 Javascript
jQuery插件Tooltipster实现漂亮的工具提示
Apr 12 Javascript
不同js异步函数同步的实现方法
May 28 Javascript
微信开发 消息推送实现代码
Oct 21 Javascript
bootstrap网格系统使用方法解析
Jan 13 Javascript
详解JS浏览器事件循环机制
Mar 27 Javascript
vue循环数组改变点击文字的颜色
Oct 14 Javascript
浅析vue中的provide / inject 有什么用处
Nov 10 Javascript
vue Element-ui表格实现树形结构表格
Jun 07 Vue.js
JS实现点击登录弹出窗口同时背景色渐变动画效果
Mar 25 #Javascript
JS实现响应鼠标点击动画渐变弹出层效果代码
Mar 25 #Javascript
JS+CSS实现鼠标经过弹出一个DIV框完整实例(带缓冲动画渐变效果)
Mar 25 #Javascript
JS+CSS实现的漂亮渐变背景特效代码(6个渐变效果)
Mar 25 #Javascript
详解Javascript继承的实现
Mar 25 #Javascript
JavaScript实现弹出DIV层同时页面背景渐变成半透明效果
Mar 25 #Javascript
JavaScript修改作用域外变量的方法
Mar 25 #Javascript
You might like
php中判断一个字符串包含另一个字符串的方法
2007/03/19 PHP
php生成二维码的几种方式整理及使用实例
2013/06/03 PHP
PHP使用pcntl_fork实现多进程下载图片的方法
2014/12/16 PHP
php防止sql注入简单分析
2015/03/18 PHP
php+Memcached实现简单留言板功能示例
2017/02/15 PHP
JS类库Bindows1.3中的内存释放方式分析
2007/03/08 Javascript
jquery keypress,keyup,onpropertychange键盘事件
2010/06/25 Javascript
JavaScript实现的in_array函数
2014/08/27 Javascript
浅谈Javascript数组索引
2015/07/29 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
2015/09/12 Javascript
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)
2016/02/26 Javascript
基于JS模仿windows文件按名称排序效果
2016/06/29 Javascript
angularjs 表单密码验证自定义指令实现代码
2016/10/27 Javascript
jQuery ajax 当async为false时解决同步操作失败的问题
2016/11/18 Javascript
Express之get,pos请求参数的获取
2017/05/02 Javascript
利用npm 安装删除模块的方法
2018/05/15 Javascript
从0到1搭建element后台框架优化篇(打包优化)
2019/05/12 Javascript
微信小程序云开发之新手环境配置
2019/05/16 Javascript
JavaScript中的ES6 Proxy的具体使用
2019/06/16 Javascript
15 分钟掌握vue-next响应式原理
2019/10/13 Javascript
js回调函数原理与用法案例分析
2020/03/04 Javascript
vue-socket.io接收不到数据问题的解决方法
2020/05/13 Javascript
js 执行上下文和作用域的相关总结
2021/02/08 Javascript
Python实现统计文本文件字数的方法
2017/05/05 Python
老生常谈Python之装饰器、迭代器和生成器
2017/07/26 Python
Linux下安装python3.6和第三方库的教程详解
2018/11/09 Python
django与vue的完美结合_实现前后端的分离开发之后在整合的方法
2019/08/12 Python
Python 多线程共享变量的实现示例
2020/04/17 Python
html5 canvas实现圆形时钟代码分享
2013/12/25 HTML / CSS
美国领先的汽车轮胎和轮毂供应商:TireBuyer
2016/07/21 全球购物
吉列剃须刀美国官网:Gillette美国
2018/07/13 全球购物
拉丁舞学习者的自我评价
2013/10/27 职场文书
2014年公务员个人工作总结
2014/11/22 职场文书
销售业务员岗位职责
2015/02/13 职场文书
和领导吃饭祝酒词
2015/08/11 职场文书
我的收音机情缘
2022/04/05 无线电