问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何在JavaScript中定义并初始化数组

发布网友 发布时间:2022-04-23 15:43

我来回答

2个回答

懂视网 时间:2022-04-23 20:04

标签(空格分隔): call apply


笔记版

编写代码中通常会有快速初始化数组的需求,例如我们需要一个类似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);// 1000a.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-fillconsole.time("no-fill");let t = Array(5e7);console.timeEnd("no-fill");// fillconsole.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中是绝对不允许的。

热心网友 时间:2022-04-23 17:12

数组初始化用中括号括起元素来就可以了。

例:

var array = [1, 2, 3];
console.log(array);

更详细的可以参考以下页面:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
2023文科男生最吃香的专业 哪些专业好就业 在南京想找上海音乐学院的老师,怎么找? 荔枝核怎么服用-荔枝核煮水一般煮几颗合适 属虎适合什么名字2022年新生儿 有内涵热门名字精选 国内读研好,还是出国读研好 出国读研和国内读研哪个更好 在一个比例中,如果两个外项互为倒数。那么两个内向的什么是一?_百度知 ... 两个外项互为倒数,一个内向是8分之3,另一个内项是多少【怎样求出来... 在一个比例中,两个外向互为倒数,其中一个内项是8,另一个内项是_百度... 在比例中两个外项互为倒数,其中一个内向是2.75,另一个内项是多少_百度... 梦见我去世的爷爷和哥哥给我们摘了好多辣椒和一个大西瓜是什么意思? 我做梦到好多花和摘西瓜 梦见和自己老公在摘大西瓜 京东退出之后为什么再登录就看不到物流信息了? 脚趾甲部分嵌入肉里,拔不出来怎么办 2015年乐清公务员考试培训哪里培训比较好? 我现在已经40多了,想学习更多关于电脑方面的知识,比如说ps,cad,办公软件,乐清哪里有这方面的培训班呢? 第一次在百度提问,乐清少儿英语口语培训班那个老师和教学质量好?那个好? 浙江省乐清市电脑培训Creo去哪里好? 有没有好点的电脑培训学校? 乐清沃尔得国际英语中心与乐清其它英语培训学校相比有什么优势?我想知道 广东广州市海珠区车船税在哪里缴纳? 西点培训班乐清有没有西点培训学校 乐清市向尚教育培训学校怎么样? 乐清市有哪些比较好的调酒师培训学校,我还学 乐清教育培训机构,进修学历,那里有好的? 乐清儿童语言训练机构有哪些 哪家比较好、比较专业,孩子快4周岁了,发音不准,说不了完整句子? 现在好像室内设计做的蛮好,想转行做这个,大家知道乐清室内设计培训哪家靠谱的吗 乐清哪家英语培训机构比较好? 乐清哪家少儿英语培训机构比较好? 坐标乐清,初中一对一,课外辅导机构哪家好?听说时代广场的快乐学教育很好 竖横勾怎么写 小学硬笔书法 横构竖钩的写法 绝缘测试之前,应将母线与其两端连接电气设备断开,用兆欧表对母线()之间进行绝缘测试? 和平精英模拟器怎么注册 笔记本电脑玩游戏突然开始掉帧是怎么回事 肥料行业质量管理怎么做? 笔记本电脑频繁掉帧,客服给的处理方法都行不通? 临沂那里有化验化工原料的,不知道是什么化工产品。需要化验下、有知道的说下具体位置或者电话 谢谢 临沂市鑫元化工有限责任公司怎么样? 临沂市产品质量监督检验所 清洗油烟机用的片碱在临沂哪里能买到 临沂市河东区锋径化工有限公司待遇怎么样? 有什么偏方能治疗小孩蛀牙牙痛的? 儿童蛀牙牙疼偏方怎么办 小孩蛀牙牙痛有没有什么偏方可以缓解一下疼痛啊? 治疗蛀牙的偏方 奖励 +5 速度 急··· 北京软件测试外包公司 有什么治蛀牙疼的偏方吗? 楚国辞赋家谁是我国第一位伟大的爱国主义诗人? 楚国辞赋家是哪个诗人