前言
最近公司找我这个菜鸟烧烤哥出春招题,第一次出题内心激动又紧张,生怕出的题别人答不上来。
或许这就是菜鸟的自信吧!
朋友,请听题
js如何快速创建长度为n且值都为1的数组?
这道题咋一看啥也不是,再一看也就那样,咋看一下:有陷阱!
抽取关键词:快速、长度为n值为1。
下面我们先看一下各种各样的备选答案。
备选答案
答案1
var a = [];
for (var i = 0; i < n; i++) {
a[i] = 1;
}
这个答案谁都懂,for循环创建数组。
答案2
for (var a = [], j= 0; j< n; a[j++] = 1);
该答案是答案1的升级,将赋值语句与循环自增结合在一起,简洁明了!
答案3
[...new Array(n).keys()].map(() => 1);
...扩展运算符对数组来说可用于将数组转变成逗号分隔的参数序列,对于对象来说就是取出参数对象的所有可遍历属性。keys() 方法用于从数组创建一个包含数组键的可迭代对象(也就是具备es6中的遍历器Iterator接口的对象)。
分解以上行为:
扩展运算符将可迭代对象的属性扩展成一个逗号分隔的参数序列。
从这里看出,可迭代对象既同时具备了对象和数组的属性。
答案4
[...Array(n)].map(() => 1);
该答案是答案3的进化版本,直接通过扩展运算符扩展初始化数组。我们发现:
数组初始化生成的是一个长度为n的空数组,但扩展运算符可以将其转化,空间es6中这个语法糖的强大之处。
答案5
Array(n).fill(1);
有人不喜欢使用map方法,所以es6给你提供了一个fill方法,一次到位,用固定值填充数组。
答案6
Array.from({ length: n }, () => 1);
Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
数组的其实也是一种对象,所以,对象和数组是近亲。那啥类数组?
- 可以通过索引访问成员,并且拥有length属性
- 不存在数组中的方法如push、forEach等
答案7
Array.apply(null, Array(n)).map(() => 1);
使用apply方法的特性,将初始化数组当作第二参数传入可以实现数组的克隆。很明显,这个比答案4差太多,不建议使用。
答案8
let arr = new Array(n),i = arr.length;
while (i--) {
arr[i] = 1;
}
这个答案很鸡贼,不是使用for循环创建初始化数组,而是通过while对数组进行赋值。结果也是可以得到目标数组。
答案n
或许你还有很多不一样的答案!
哪种答案最correct
接下来我们从性能、可读性来对比这几种答案。
为让我们的对比更有高效,首先需要排除掉答案2、答案7,这两个答案看起来就不是好答案!
性能对比
很多同学做代码的性能对比首先想到的就是运行时间的对比,烧烤哥也是这样。但是烧烤哥的测量的手段比较专业!并不是下面代码所示的简单测量。
console.time('性能测试');
//运行代码
console.timeEnd('性能测试');
烧烤哥使用的是专业的测试工具benchmarks: 一个可靠的js基准测试工具。有兴趣的可以看看github上的指引。
基准测试是一种测量和评估软件性能指标的活动,对于js而言,可以保证运行上下文的不变从而得出公平的测试结果。
测试代码如下
const Benchmark = require('benchmark');
const suite = new Benchmark.Suite;
const n = 1000000;
suite.add('答案1', function() {
let a = [];
for (var i = 0; i < n; i++) {
a[i] = 1;
}
})
.add('答案3', function() {
[...new Array(n).keys()].map(() => 1);
})
.add('答案4', function() {
[...Array(n)].map(() => 1);
})
.add('答案5', function() {
Array(n).fill(1);
})
.add('答案6', function() {
Array.from({ length: n }, () => 1);
})
.add('答案8', function() {
let arr = new Array(n),i = arr.length;
while (i--) {
arr[i] = 1;
}
})
.on('cycle', function(event) {
console.log(String(event.target));
})
.on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run({ 'async': true });
运行结果:nodejs版本为 v12.14.1
n值 | 结果 | n=1000000 | n=100000 | n=10000 |
---|
运行结果:nodejs版本为 v10.12.0
n值 | 结果 | n=1000000 | n=100000 | n=10000 |
---|
图片中的Ops/sec是指每秒钟执行测试代码的次数,后面的百分号是指误差率。
可以看出答案5和答案8的性能指标对比其他的答案都遥遥领先!
代码可读性
判断代码可读性,完全是烧烤哥的主观意志,如有雷同,兴甚至哉!
答案1 | 答案3 | 答案4 | 答案5 | 答案6 | 答案8 | 可读性 | 强 | 弱 | 中 | 中 | 中 | 弱 | 科技感 | 弱 | 强 | 强 | 强 | 中 | 弱 |
---|
所以
从性能和代码可读性来看,答案5更胜一筹:
Array(n).fill(1);
可是,fill方法是es6的对数组新加的方法,在低版本浏览器和node中不能愉快的使用,所以这时候可以退而求其次使用一下其他看起来还行的方式:如while、for循环。
当然
这种对比其实毫无意义,除非你创建数组的时候:
n=100000000
还有就是你面试的时候!
除此之外,你可以随意使用!
最后
觉得烧烤哥写的不错的,点赞关注吧;如有不足的地方,请不吝指正。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!