文档章节

[JavaScript]-Array构造的数组使用map为何失效?

xiaoLoo
 xiaoLoo
发布于 2018/06/27 16:25
字数 730
阅读 24
收藏 0

img

[示例]

假设你需要生成一个从0到99的数组。你要怎么做呢?下面是一种解法:

const arr = [];
for (let i = 0; i < 100; i++) {
  arr[i] = i;
}

看到这种使用传统的for循环的方式会有点不大习惯。事实上,各种高阶函数,像forEach, map, filter, reduce足以写出各种漂亮的代码。

也许你还没有沉醉于函数式编程的美妙,那么你会认为上面的解法足矣。不过,如果你用过高阶函数编程,你也许就会想:一定还有更加优雅的实现方法。

我的第一直觉就是:首选创建一个长度为100的空数组,然后由map用index去初始化每一个元素。在JavaScript中,你可以用Array构造函数来创建数组:

const arr = Array(100);

接下来你只需要用map就可以解决问题了:

const arr = Array(100).map((_, i) => i);
console.log(arr[0] === undefined);  // true

可是,为什么第一个元素不是0而是undefined?

[解释]

为了理解为何没有生效,我需要首先讲清楚一个非常重要的技术点。在内部,JavaScript数组实际上是对象,对象里面的属性名是数字,对应数组的下标。举个例子:

['a', 'b', 'c']

它实际上等价于:

{
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
}

当你去访问数组的第0个元素的时候,实际上访问的是对象中属性名为0的元素。接下来我们会解释为何刚刚的代码没有效果。

当你使用Array构造函数来新建一个数组,那么它会创建一个新的数组对象,并且将长度length设定为指定的值。但是,对象里面没有数组索引:

{
  //no index keys!
  length: 100
}

当你去访问数组的第0个元素的时候,返回值为undefined。但并不是指第0个元素得值为undefined,而是当数组下标不存在的时候,默认的返回值。

并且如果数组下标不存在的话,其实map函数并没有真正的对每一个元素执行操作。因为只有当下标存在的时候,map的回调函数才会执行. console

[解法]

因此,我们只需要在数组对象中构造出数组的下标就可以了。最好的方法就是用展开运算符:

const arr = [...Array(100)].map((_, i) => i);
console.log(arr[0]);
// 0

使用展开运算符后的数组对象:

{
  0: undefined,
  1: undefined,
  2: undefined,
  ...
  99: undefined,
  length: 100
}

就可以顺利使用map函数了。

© 著作权归作者所有

xiaoLoo
粉丝 5
博文 36
码字总数 22674
作品 0
西安
程序员
私信 提问
Array构造的数组使用map为何失效?

译者按: Array函数构造的数组没有初始化索引,无法使用map函数。 原文: Here’s Why Mapping a Constructed Array in JavaScript Doesn’t Work 译者: Fundebug 为了保证可读性,本文采用意...

Fundebug
2018/06/27
0
0
《es6 标准入门》知识整理(2) - 数据类型的扩展、Set 和 Map

字符串的扩展 es6 为字符串添加了遍历器接口,使得字符串可以被 for...of 循环遍历 at(), charAt() 返回字符串给定位置的字符 normalize() 用来将字符的不同表示方法统一为同样的样式,这称...

IrisHuang
04/09
0
0
JavaScript中Promise使用

定义 Promise对象用于包装异步函数执行结果,以便用同步的方式处理其结果。 promise 包含3种状态: pending: 初始状态 fulfilled: 完成状态 rejected: 失败状态 链式调用方法 then()返回一个...

王桥修道院副院长
01/12
0
0
javaScript 常用 API 实例讲解

模拟 New 操作符 new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例 创建一个空的简单 JavaScript 对象(即 {}); 连接该对象(即设置该对象的构造函数)到另一个...

叫我小明呀
05/29
0
0
温故js系列(13.2)-有意思的30题_解析

前端学习:教程&开发模块化/规范化/工程化/优化&工具/调试&值得关注的博客/Git&面试-前端资源汇总 欢迎提issues斧正:30题_解析 JavaScript-有意思的30题-解析 之前在学习时把问题和答案分开...

xzavier
2018/08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

所以说这才是Redis进化史吗?看Redis是如何变成最强缓存的

写在前面:笔者翻阅了很多资料,只能找到Redis2.2及以后的主要版本的发布日志。所以,让我们从2.2开始一步一步深入了解Redis。 2.2 redis-cli命令非常大的改进: Tab补全,支持help(例如help ...

Java干货分享
56分钟前
6
0
manjaro抽风,/usr/lib/modules目录丢失

现象 2019年6月16日这周,突然发现manjaro抽风: 先是启动时无法加载一些内核模块,导致启动失败 然后用启动盘重新pacman -S linux,第一次启动是好的,再启动就有问题了 原因 翻来覆去搞不定...

chuqq
今天
5
0
MyClouds-2.0-RC 发布,企业级微服务平台

MyClouds企业级微服务平台 MyClouds-V2.0-RC 已发布。 更新如下 [优化] 重构了系统架构。(移除myclouds-admin-webserver工程,停用后端thymeleaf模版引擎,前后端彻底分离;移除了myclouds-...

xiongchun
今天
1
0
Wine-Staging 4.9 发布,增添一些新补丁

Wine-Staging的工作还在继续,到4.9版为止,在上游Wine代码库上有超过830个补丁。 在上周五的Wine 4.9发布之后,Wine-Staging 4.9已经发布了,之前的一些暂存工作现在围绕Windows编解码器和D...

linuxCool
今天
2
0
JAVA8新特性(吐血整理)

一、Java 8 Lambda 表达式 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。 Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。 使用Lambda 表达式可以...

天王盖地虎626
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部