Array构造的数组使用map为何失效

译者按: Array函数构造的数组没有初始化索引,无法使用map函数。

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

示例

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

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

如果你和我一样,看到这种使用传统的for循环的方式会有点不大习惯了。事实上,我已经好多年不使用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的回调函数才会执行。

解法

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

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

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

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

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

关于Fundebug

Fundebug专注于JavaScript、微信小程序、小游戏BUG监控,自从2016年双十一正式上线,Fundebug已经服务了一年半时间,累计处理了5亿+错误事件,得到了众多知名用户的认可。Fundebug支持主流前端框架的bug监控,欢迎各位老铁体验!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Web 开发

JavaScript的对象引用

在一个函数体内,var变量声明的变量,其作用域只在该函数体内,对于函数体外而言,是不可见的(废话)。

690
来自专栏磐创AI技术团队的专栏

干货 | 如何写一个更好的Python函数?

《Writing Idiomatic Python》一书的作者在Medium上发表了一篇文章,给出了6个建议。

401
来自专栏腾讯Bugly的专栏

那些年,我们一起写过的“单例模式”

本文来自:“天天P图攻城狮”公众号(ttpic_dev) 题记 度娘上对设计模式(Design pattern)的定义是:“一套被反复使用、多数人知晓的、经过分...

4114
来自专栏皮皮之路

【JDK1.8】Java 8源码阅读汇总

1264
来自专栏mySoul

设计模式-结构型模式-装饰模式

登录页面数据上报,使用装饰器,将登录层页面,上传到上报类中,进行装饰上统计代码,然后将统计数据上报。

502
来自专栏解决发现

CPU占用率100%的解决方法

图:优化前(我的电脑是四核cpu,所以单线程无限无阻塞循环占用率不会达到100%)

1530
来自专栏积累沉淀

Java设计模式(十四)----模板方法模式

模板方法模式 一、概述 二、结构 三、具体案例 四、优缺点和设计思想 一、概述 模板方法模式是类的行为模...

1955
来自专栏量子位

干货 | 如何写一个更好的Python函数?

《Writing Idiomatic Python》一书的作者在Medium上发表了一篇文章,给出了6个建议。

652
来自专栏C/C++基础

我所理解的C++反射机制

在实际的项目中,听到师兄说C++中用到了反射,出于好奇,就查阅相关资料,发现强大的C++本身并不支持反射,反而Java支持反射机制。当我得知这个事实时,一直唯C...

562
来自专栏Java Edge

设计模式实战-迭代器模式

迭代器是为容器服务的,那什么是容器呢? 能容纳对象的所有类型都可以称之为容器,例如Collection集合类型、Set类型等,迭代器模式就是为解决遍历这些容器中...

842

扫码关注云+社区