编写代码中通常会有快速初始化数组的需求,例如我们需要一个类似matlab里的zeros函数,假如这里我们需要生成一个0-23的数组用于表示一天24小时。

最基本的做法如下:

function(){
let hours = [];
for(let k = 0; k < 24; k++ )hours.push(k);
return hours;
}

下面我们来思考如何用更优雅的方式实现。

考虑使用new Array(24)+ map的方法来实现。

代码如下:

Array(24).map((_, h) => h);

注意,这里map的第二个参数是索引,平时用的少,这里把索引作为数值。

结果与预期并不符合,为啥呢?

简单搜索了一下,发现时因为js里的稀疏数组的逻辑导致的。

我们先看一下下面的代码:

let a = [];
a[1000] = 2;
console.log(a.length);
// 1000
a.forEach(x => console.log("hello"));
// only one "hello"

js的处理逻辑是,对于没有主动赋值的位置进行“空置”处理,对于这些“空置”未知,迭代器是不会理会的,这么做最主要的目的就是避免不合理的赋值操作导致的bug。

假设没有这种逻辑,我们写下了new Array(Date.now()),这将导致系统新建一个非常大的数组,而实际上啥也没存。

我们可以吧new Array(len)干的事情简单理解为下面的过程:

function(len){
let r = [];
r.length = len;
return r;

这就是为什么对new Array(len)调用map或者forEach的时候跟预期不一致了。

如何解决这一问题呢,除了使用new Array(len)的形式,我们还可以使用new Array(1,2,3)这种写法来初始化数组,但是这么写就没法实现我们编写初始化数组的目的了。

这个时候我们想到了apply,这个函数的第二个参数正好就是一个数组,于是我们写下了下面的代码。

// 借用apply
Array.apply(null, Array(24)).map((_, h) => h);
// [0, 1, ..., 24]

得到了我们希望的结果。这就说明,Array(24)apply中作为参数的时候是被当做24个值对待的,因为这一点就保证了最后得到的数组长度是24。

既然如此,我们当然同样可以使用apply的姊妹函数call

// 借用call
Array.call(null, ...Array(24)).map((_, h) => h);
// [0, 1... 23]

这也更确认了一件事,Array(len)解构会得到len个参数而非一个参数,当然call的使用必须在支持解构操作符的环境中。

在熟悉了callapply的原理后,我们可以进一步写出下面的代码:

// Array本身
Array(...Array(24)).map((_, h) => h);
// [0, 1, ..., 24]

这种形式已经足够优雅了。

另外,在ES6中,Array提供了新方法fill,借用该方法填充那些“空置”位,进而保证后续的操作能顺利进行。

具体代码如下:

// 推荐
Array(24).fill(null).map((_, h) => h);

现在也比较推荐最后一种写法,这种方法也最为直观。

不过需要注意fill方法的使用,应该尽量避免盲目地填充,因为这样会上面提到了js设计“空置”逻辑为了避免的bug。

有兴趣的可以尝试一下下面的代码:

// no-fill
console.time("no-fill");
let t = Array(5e7);
console.timeEnd("no-fill");
// fill
console.time("fill");
let q = Array(5e7).fill(null);
console.timeEnd("fill");
// => no-fill: 0.240ms
// => fill: 3247.921ms

在浏览器中尝试浏览器基本会不响应,没有设置更大的数值为了避免得不到结果。假设一个int占用4个字节的内存,这个fill会占用200M的内存,且需要循环5千万次,这必然会占用大量的CPU和内存,在单线程的js中是绝对不允许的。

javascript快速初始化数组的更多相关文章

  1. JavaScript中的数组创建

    JavaScript中的数组创建 数组是一个包含了对象或原始类型的有序集合.很难想象一个不使用数组的程序会是什么样. 以下是几种操作数组的方式: 初始化数组并设置初始值 通过索引访问数组元素 添加新元 ...

  2. C数组&结构体&联合体快速初始化

    背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组某些元 ...

  3. C89,C99: C数组&结构体&联合体快速初始化

    1. 背景 C89标准规定初始化语句的元素以固定顺序出现,该顺序即待初始化数组或结构体元素的定义顺序. C99标准新增指定初始化(Designated Initializer),即可按照任意顺序对数组 ...

  4. javascript中快速求数组的全部元素的相加之和

    js中快速求数组的全部元素的相加之和: var arr = [1,2,3,4,5];var sum = eval(arr.join('+')); console.log(sum); 运行结果: 15

  5. JavaScript权威指南 - 数组

    JavaScript数组是一种特殊类型的对象. JavaScript数组元素可以为任意类型,最大容纳232-1个元素. JavaScript数组是动态的,有新元素添加时,自动更新length属性. J ...

  6. javascript中关于数组的一些鄙视题

    一.判断一个数组中是否有相同的元素 /* * 判断数组中是否有相同的元素的代码 */ // 方案一 function isRepeat1(arrs) { if(arrs.length > 0) ...

  7. JavaScript Array(数组)对象

    一,定义数组 数组对象用来在单独的变量名中存储一系列的值. 创建 Array 对象的语法: new Array(); new Array(size); new Array(element0, elem ...

  8. JavaScript学习笔记-数组(1)

    数组是值的有序集合.每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引.JavaScript数组是无类型的:数组元素可以是任意类型,并且同一个数组中的不同元素也可能有不同的类型.数 ...

  9. JavaScript快速入门(四)——JavaScript函数

    函数声明 之前说的三种函数声明中(参见JavaScript快速入门(二)——JavaScript变量),使用Function构造函数的声明方法比较少见,我们暂时不提.function func() { ...

  10. JavaScript中对数组的操作

    原文:JavaScript中对数组的操作 一:数组的使用 1.定义:JavaScript中对数组的定义有两种形式.如: .var arr = [12,3,5,8]; .var arr = new Ar ...

随机推荐

  1. 解决phpmyadmin导入MYSQL数据库限制大小为50M的问题

    有时候想导入的数据库太大.但是遭到的限制 解决phpmyadmin导入MYSQL数据库限制大小为50M的问题 转载于:https://www.cnblogs.com/wesky/p/10609340. ...

  2. Qt编写视频监控系统71-外网访问摄像头等设备(获取各种信息及拉流)

    一.前言 最近遇到个需求是通过外网接入摄像机或者NVR,通用的做法是将视频流推流到服务器,然后拉取rtmp视频流,这样就多了服务器的要求,而且实现的功能有限比如不能直接用onvif协议对设备获取信息和 ...

  3. C# 设置label(标签)控件的背景颜色为透明

    有时候,我们需要将控件的背景颜色设定为透明,比如说label(标签)控件.那么,如何将控件的背景颜色设定为透明?是不是只要将控件的BackColor属性设为Transparent(透明)就可以了呢?答 ...

  4. 深入Python胶水语言的本质:从CPython到各类扩展机制

    在开始深入讲解Python如何作为胶水语言之前,我们需要先了解Python语言本身的实现机制.这对于理解Python如何与C语言交互至关重要. CPython:Python的默认实现 当我们谈论Pyt ...

  5. 使用学生优惠创建 Azure Database for MySQL 数据库

    前言 在此之前,你需要拥有一个已通过学生认证的 Azure 账户.关于通过 Azure 学生认证,网上已有大量教程,此处不再赘述. 前些日子认证通过了 Azure 的学生认证,在部署此网站时发现 Az ...

  6. 前端vue项目本地运行内网访问的方法

    有时候在公司里,领导想在内网访问到你本地的项目,所以就有了前端项目内网访问 (1)首先在package文件里面的host改成0.0.0.0,像这个样子 (2)其次在config下的index.js里的 ...

  7. 从v-for的key说起

    一.v-for中的key是为什么存在呢? 这是vue官网给key的定义,key主要用于vue的虚拟dom算法.新的问题出现了,vue的虚拟dom算法是什么? 二.虚拟domg算法 我们的程序在运行时, ...

  8. Hutch PG walkthrough Intermediate window

    NMAP └─# nmap -p- -A -sS 192.168.196.122 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-16 01 ...

  9. changeServer.sh一键切换服务器脚本

    直接看改进版2.0 切换服务器,免密登录vi changeServer.sh #!/bin/bash #authe by wangxp export IFCFG=/etc/sysconfig/netw ...

  10. Atcoder ABC387F Count Arrays 题解 [ 绿 ] [ 基环树 ] [ 树形 dp ] [ 前缀和优化 ]

    Count Arrays:一眼秒的计数题. 思路 显然,把小于等于的条件化为大的向小的连单向边,每个数的入度都是 \(1\),就会形成一个基环树森林. 那么考虑这个环上能填什么数.因为所有数都小于等于 ...