前端Tips#2 - 将 arguments 转换成Array的最佳实践

本文同步自 JSCON简时空 - 技术博客,点击阅读

视频讲解

视频地址javascript

文字讲解

一、先讲结论

有不少种方式将 arguments 转换成数组,那么哪种方式是最优的?html

为节约大伙儿的时间,这里先说一下结论:若是你想将 arguments 转换成数组,最好的方式是使用 rest 参数转换的方式(即便用 ... spread 操做符),好比:前端

function test(…args) {
   console.log(args)
}
test(1,2,3); // [1,2,3]

缘由是:性能是 最优 的,可读性也挺好。java

想知道为何的话,能够继续往下看。node

二、缘由分析

arguments 对象是全部(非箭头)函数中均可用的局部变量,它是一个 “Array-Like” 对象,即 “像数组的对象”的意思,有些文章中也会翻译成 “伪数组对象”。(能够按索引取值、具备 length 属性,但不必定具有 pushconcat 等数组方法,具体可参考文章伪数组(ArrayLike)内容)git

!> 注意:箭头函数中并不存在 arguments 对象github

本期 tip 并不去详细讲 arguments 对象的知识内容(具体知识内容可阅读本讲末尾的参考文章),本讲着重讲解把它转换成数组时的最佳实践。编程

浏览了许多技术文章,将 arguments 对象转换成数组基本是 4 种方式:segmentfault

  1. 使用 Array.prototype.slice.call(arguments)进行转换,或者是使用等效方法 [].slice.call(arguments);
  2. 使用 Array.from(arguments) 进行转换
  3. 使用 for 循环挨个将 arguments 对象中的内容复制给新数组中
  4. 利用 ES6 中的 rest 参数转换,let a = (...args) => args;

大多数文章也仅仅是讲到这里为止,并无继续讨论以上哪一种方式最优。数组

接下来咱们就用基准测试(Benchmark)的方式来量化上述那种方式性能更好。

三、性能测试

在《作好准备:新的V8即将发布,Node 的性能正在改变》文中给告终论:

result

我将这文中说起的测试代码扔到 jsPerf 网站上(测试地址:https://jsperf.com/rest-argum... ),运行结果以下:

benchmark result

图中数值越高表明性能越好,以上两幅图所反映的结果是一致的:

  1. 利用 ES6 中的 rest 参数转换性能最好
  2. 其次使用 for 循环方式转换
  3. [].slice 的方式性能较弱
  4. 最差的就是用 Array.from 进行转换
也可本地进行性能测试,测试代码在 这儿 获取;源码来自 官方提供的 benchmark 示例

所以,若是你想要将 arguments 转换成数组,那么毫无疑问应当使用 ES6 中的 rest 参数转换方式。

除了性能更好以外,rest 参数的用法相对于直接使用 arguments 还有以下优势:

  1. 箭头函数和普通函数均可以使用。
  2. 更加灵活,接收参数的数量彻底自定义。
  3. 可读性更好,参数都是在函数括号中定义的,不会忽然出现一个arguments,显得很突兀。

四、Q & A

在这里我简单解答一些常见的疑惑:

Q: 为何须要将 arguments 对象转换成数组?

A: 答案也简单,由于 Array 实例提供了不少数组方法,好比 .push.concat 等,提供了更多数据操做方式,归根到底,转换成数组就是为了方便操做数据。

Q: 既然常常要将 arguments 转换成数组,为何最初不把 arguments 设计成数组格式呢?

A: 按照文章 《JavaScript arguments 对象全面介绍》所言, arguments 在语言的早期就引入了,当时的 Array 对象具备 4 个方法: toStringjoinreversesortarguments 继承于 Object 的很大缘由是不须要这四个方法。(当时设计的人也不知道后续的发展会对 arguments 有这方面的强需求...变化无处不在..)

Q: 为何须要 Array-Like 对象(伪数组对象)的存在?

A: 前面说了,转换成数组也是为了提供更多数据操做方式;其实 Array-Like 对象的存在,也是为了给数据提供更多的操做的可能,由于能够在对象上挂载不少 自定义 的操做方法,使用起来灵活度会很高。

Q: 上述讨论的数组转换结果,是否也适应于其余 “伪数组对象”?

A: 由于 arguments 也是“伪数组对象”,不难推而广之,上面讨论的数组转换的方式均可以应用在“伪数组对象”上;至于每一个转换方法的性能如何,我由于没有单独去测试过,因此也不能妄下定论,你们能够本身写 benchmark 去测试一下(我的猜想应该结论也差很少)。

五、参考文章


关于 “前端Tips专栏”

前端Tips”专栏,隶属于 JSCON 专栏系列,设计初衷是快速获取前端小技巧知识,取材普遍,涵盖前端编程诸多领域。设计初衷是快速消费类知识,因此每一个 tips 阅读耗时大约 5 分钟。为方便读者在不一样场合阅读,每篇 tips 配有视频音频文字,挑本身喜欢方便的就行。

有两种方式获取历史 tips:

① 在公众号内回 "tips" +"期号" 就能够。例如:回复 “tips25” 便可获取第25期 tips
② 前往网站:https://boycgit.github.io/fe-...里面提供了搜索功能

欢迎你们关注个人知识专栏,更多内容等你来挖掘

我的微信公众号

相关文章
相关标签/搜索