资讯专栏INFORMATION COLUMN

ECMAScript6(6):数组的扩展

DrizzleX / 1393人阅读

摘要:数组的扩展将类数组对象和可遍历对象转化为真正的数组。这两个函数的参数都是回调函数。遍历数组找到符合条件回调函数返回为的第一个值返回其值返回其下标。这三个方法用来遍历数组返回一个遍历器供使用其中是对键的遍历是对值的遍历是对键值对的遍历。

数组的扩展

Array, from()

将类数组对象和可遍历对象转化为真正的数组。

var arrayLike = {
  "0" : "a",
  "1" : "b",
  "2" : "c",
  "length": 3
}

var arr;
//ES5
arr = [].slice.call(arrayLike);    //arr=["a", "b", "c"]

//ES6
arr = Array.from(arrayLike);    //arr=["a", "b", "c"]

和它类似的是扩展运算符, 一样可以实现该功能(要求对象具有遍历器接口):

function(){
  var arg = [...arguments];   //转化 arguments 为数组
}

Array.from() 接受第二参数(函数), 用来映射结果, 相当于 map, 并且可以用第三个参数绑定 this:

Array.from(obj, func, context);
//等价于
Array.from(obj).map(func, context);

技巧, 用 Array.from() 指定函数运行次数:

var i = 0;
Array.from({length: 3}, ()=>i++);   //[0, 1, 2]

建议:使用Array.from方法,将类似数组的对象转为数组。

Array.of()

将多个值组成数组:

Array.of(2, 3, 5);   //[2, 3, 5]
Array.of(2);   //[2]
Array.of();   //[]
Array.of(undefined);   //[undefined]

Array.prototype.copyWithin()

函数参数是 Array.prototype.copyWithin(target, start=0, end=this.length), 对当前数组, 从截取下标为 start 到 end 的值, 从target 位置开始覆盖 this 中的值。如果 start 或 end 为负数则倒数。

[1, 2, 3, 4, 5].copyWithin(0, 3, 4);   //[4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, -2, -1);   //[4, 2, 3, 4, 5]

[].copyWithin.call({length: 5, 3: 1}, 0, 3);   //{0: 1, 3: 1, length: 5}

var i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);   //[3, 4, 5, 4, 5]

Array.prototype.find(), Array.prototype.findIndex()

这两个函数的参数都是回调函数。遍历数组, 找到符合条件(回调函数返回为true)的第一个值, find()返回其值, findIndex()返回其下标。如果没找到符合条件的值find()返回undefined, findIndex()返回-1。

[1, 2, -3, 4].find((item) => item < 0);   //-3
[1, 2, -3, 4].findIndex((item) => item < 0);   //2

[NaN].findIndex(y => y !== y);   //0
[NaN].indexOf(NaN);   //-1, indexOf 找不到 NaN

这两个函数还接受第二参数, 用来绑定回调函数中的 this

Array.prototype.fill()

完整形式: Array.prototype.fill(value, start=0, end=this.length), 对数组 start 到 end 直接部分填充 value, 覆盖原有值。

[1, 2, 3, 4, 5].fill("a", 2, 4);    //[1, 2, "a", "a", 5];
var arr = new Array(5).fill(0);   //arr = [0, 0, 0, 0, 0];

Array.prototype.entries(), Array.prototype.keys(), Array.prototype.values()

这三个方法, 用来遍历数组, 返回一个遍历器, 供 for...of 使用, 其中 keys()是对键的遍历, values() 是对值的遍历, entires()是对键值对的遍历。babel 已实现

var a = ["a", "b", "c"];

for(let item of a.values()){
  console.log(item);     //依次输出 "a", "b", "c"
}

for(let key of a.keys()){
  console.log(key);     //依次输出 0, 1, 2
}
for(let pair of a.entries()){
  console.log(pair);     //依次输出 [0, "a"], [1, "b"], [2, "c"]
}

当然也可以用遍历器的 next() 方法遍历

var a = ["a", "b", "c"];
var values = a.values();
console.log(values.next().value);   //"a"
console.log(values.next().value);   //"b"
console.log(values.next().value);   //"c"

Array.prototype.includes()

这是个 ES7 的方法, 判断数组中是否含有某个值, 含有则返回 true, 否则返回 false。可以用第二个参数指定查找起始点(小于0倒数)。

//该方法同样可以找到 NaN, 而 indexOf 不行
[1, 2, NaN].includes(NaN);   //true
[1, 2, 3, 4, 5].includes(2, 3);  //false

数组的空位

我们比较以下两个数组:

var empty = new Array(3);  //[, , , ]
var unempty = new Array(3).fill(undefined);   //[undefined, undefined, undefined]

console.log(0 in empty);     //false
console.log(0 in unempty);   //true

结合手册内容如下就很好理解这个问题:

“Array elements may be elided at the beginning, middle or end of the element list. Whenever a comma in the element list is not preceded by
an AssignmentExpression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the
Array and increases the index of subsequent elements. Elided array elements are not defined. If an element is elided at the end of an array,
that element does not contribute to the length of the Array.”
摘自ECMAScript® 2015 Language Specification

翻译如下。

"数组成员可以省略。只要逗号前面没有任何表达式,数组的length属性就会加1,并且相应增加其后成员的位置索引。被省略的成员不会被定
义。如果被省略的成员是数组最后一个成员,则不会导致数组length属性增加。”

很明显, 一个完全空的数组是没有东西的, 而填充了undefined的数组并不是空的。
结合 ES5, 发现不同函数方法对空位处理方式是不一样的:

forEach(), filter(), every(), some() 会忽略空值

map(), copyWithin() 会保留空值, 但不做处理

join(), toString(), 会把空值处理为空字符串

fill() 不区分空值与非空值

Array.from(), 扩展运算符(...), for...of, entires(), keys(), values(), find(), findIndex() 会视空值为 undefined

如果你记不住这些, 或者为了程序的健壮性, 可维护性, 尽量避免在数组中出现空值。
举个实例, 理解一下这个问题:

新建一个长为200的数组, 并初始化每个位置的值等于其索引
//错误方法
var arr = new Array(200).map(function(item, index){
  return index;
});
console.log(arr);    //[undefined × 200]
//正确做法
var arr = new Array(200).join().split(",").map(function(item, index){
  return index;
});
console.log(arr);    //[1, 2, 3, ..., 200]

数组推导

这是一个 ES7 的功能, 暂时还没能实现。我们可以先看一下它如何推导的:

var a1 = [1, 2, 3, 4];
var a2 = [for( i of a1) i * 2];   //a2=[2, 4, 6, 8]

不难看出, 数组 a2 通过 for...of 直接从 a1 生成。但是它的功能不仅仅这么简单, 还可以有 if 条件:

var a1 = [1, 2, 3, 4];
var a3 = [for( i of a1) if(i > 2) i * 2];   //a3=[6, 8]

这样, 我们可以简单的用数组推导模拟 map(), filter() 方法了。比如上面2个例子等价于:

var a1 = [1, 2, 3, 4];
var a2 = a1.map( (i) => i * 2 );
var a3 = a1.filter( (i) => i > 2 ).map( (i) => i * 2 );

当然我们还可以用多个 for...of 构成循环嵌套:

var a = ["x1", "x2"];
var b = ["y1", "y2"];

[for(i of a) for(j of b), console.log(i+", "+j)];
//输出
//["x1", "y1"]
//["x1", "y2"]
//["x2", "y1"]
//["x2", "y2"]

数组推导由 [] 构建了一个作用域, 其内部新建的变量, 等同于用 let 关键字声明的变量。除此之外, 字符串也可以被视为数组, 所以同样可以使用数组推导:

[for(c of "abcde"). c+"."].join("");  //"a.2.3.4.5."

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97451.html

相关文章

  • ECMAScript6 新特性——“对象扩展

    摘要:属性的简洁表示法允许直接写入变量和函数作为对象的属性和方法。,中有返回一个数组,成员是参数对象自身的不含继承的所有可遍历属性的键名。对象的扩展运算符目前,有一个提案,将解构赋值扩展运算符引入对象。 1 属性的简洁表示法 ES6允许直接写入变量和函数作为对象的属性和方法。 写入属性 var name = value; var obj = { name }; console.log...

    Clect 评论0 收藏0
  • ECMAScript6 新特性——“数组扩展

    摘要:原来的也被修改了数组实例的喝方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为的成员,然后返回该成员。数组实例的方法使用给定值,填充一个数组。 1 Array.from() Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括...

    Eminjannn 评论0 收藏0
  • ECMAScript6 新特性——“函数扩展

    摘要:返回空字符串,返回将一个具名函数赋值给一个变量,则和的属性都返回这个具名函数原本的名字。不可以使用对象,该对象在函数体内不存在。等到运行结束,将结果返回到,的调用帧才会消失。 1 函数参数的默认值 ES6允许为函数的参数设置默认值,即直接写在参数定义的后面: function log(x = message.,y = duration infomation.) { consol...

    Jiavan 评论0 收藏0
  • ECMAScript6(5):函数扩展

    摘要:否则调用时依然需要传参报错注意这里不能用触发默认值这里我们还需要单独讨论一下默认参数对的影响很明显,默认参数并不能加到中。关于作用域集中在函数扩展的最后讨论。那如果函数的默认参数是函数呢烧脑的要来了如果基础好那就根本谈不上不烧脑。 参数默认值 ES5中设置默认值非常不方便, 我们这样写: function fun(a){ a = a || 2; console.log(a); ...

    afishhhhh 评论0 收藏0
  • 常用ECMAScript6语法归纳

    摘要:对象的解构赋值函数执行后,返回的是一个对象。分别取出对象中属性为和的值,根据解构赋值的规则,在左侧声明变量,放在大括号中,变量名要和属性名保持一致。箭头函数在中,箭头函数就是函数的一种简写形式允许使用箭头定义函数。 原文博客地址,欢迎学习交流:点击预览 声明变量 可以使用let、const关键字声明变量,而不推荐使用var声明变量 var声明变量的问题: 可以多次重复声明同一个变量...

    raledong 评论0 收藏0

发表评论

0条评论

DrizzleX

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<