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 相关文章推荐
一个判断email合法性的函数[非正则]
Dec 09 Javascript
锋利的jQuery 第三章章节总结的例子
Mar 23 Javascript
从jQuery.camelCase()学习string.replace() 函数学习
Sep 13 Javascript
javascript常用的方法分享
Jul 01 Javascript
分享五个有用的jquery小技巧
Oct 08 Javascript
js制作可以延时消失的菜单
Jan 13 Javascript
bootstrap daterangepicker汉化以及扩展功能
Jun 15 Javascript
浅谈ES6新增的数组方法和对象
Aug 08 Javascript
vue2.0 实现导航守卫(路由守卫)
May 21 Javascript
js实现移动端轮播图
Dec 21 Javascript
JS事件绑定的常用方式实例总结
Mar 02 Javascript
JavaScript 替换所有匹配内容及正则替换方法
Feb 12 Javascript
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时间格式控制符对照表分享
2013/07/23 PHP
提高PHP编程效率的方法
2013/11/07 PHP
VPS中使用LNMP安装WordPress教程
2014/12/28 PHP
ThinkPHP控制器详解
2015/07/27 PHP
firebug的一个有趣现象介绍
2011/11/30 Javascript
JavaScript限定复选框的选择个数示例代码
2013/08/25 Javascript
javascript删除字符串最后一个字符
2014/01/14 Javascript
jQuery自定义添加&quot;$&quot;与解决&quot;$&quot;冲突的方法
2015/01/19 Javascript
javascript实现checkbox复选框实例代码
2016/01/10 Javascript
Angularjs中如何使用filterFilter函数过滤
2016/02/06 Javascript
jQuery获取Table某列的值(推荐)
2017/03/03 Javascript
layui select动态添加option的实例
2018/03/07 Javascript
layui问题之模拟select点击事件的实例讲解
2018/08/15 Javascript
使用Three.js实现太阳系八大行星的自转公转示例代码
2019/04/09 Javascript
一文看懂如何简单实现节流函数和防抖函数
2019/09/05 Javascript
js原生map实现的方法总结
2020/01/19 Javascript
JavaScript实现移动端弹窗后禁止滚动
2020/05/25 Javascript
Antd的Table组件嵌套Table以及选择框联动操作
2020/10/24 Javascript
JavaScript实现图片合成下载的示例
2020/11/19 Javascript
Python基于回溯法子集树模板解决0-1背包问题实例
2017/09/02 Python
python使用xlrd和xlwt读写Excel文件的实例代码
2018/09/05 Python
Python递归函数实例讲解
2019/02/27 Python
Python如何实现Paramiko的二次封装
2021/01/30 Python
一个基于canvas的移动端图片编辑器的实现
2020/10/28 HTML / CSS
MAC Cosmetics巴西官方网站:M·A·C彩妆
2019/04/18 全球购物
雅诗兰黛澳大利亚官网:Estée Lauder澳大利亚
2019/05/31 全球购物
马来西亚排名第一的宠物用品店:Pets Wonderland
2020/04/16 全球购物
设计总监岗位职责
2013/12/07 职场文书
电子商务网站的创业计划书
2014/01/05 职场文书
护士在校生自荐信
2014/02/01 职场文书
会议邀请书范文
2014/02/02 职场文书
五星级酒店餐饮部总监的标准岗位职责
2014/02/17 职场文书
儿童生日会策划方案
2014/05/15 职场文书
车间主任岗位职责范本
2015/04/08 职场文书
企业反腐倡廉心得体会
2015/08/15 职场文书
CSS文本阴影 text-shadow 悬停效果详解
2022/05/25 HTML / CSS