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

视频讲解

文字讲解

1、先讲结论

有很多种方式将 arguments 转换成数组,那么哪一种方式是最优的?

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

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

原因是:性能是 最优 的,可读性也挺好。

想知道为什么的话,可以继续往下看。

2、原因分析

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

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

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

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

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

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

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

3、性能测试

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

我将这文中提及的测试代码扔到 jsPerf 网站上(测试地址:https://jsperf.com/rest-arguments-slice ),运行结果如下:

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

  1. 利用 ES6 中的 rest 参数转换性能最好
  2. 其次使用 for 循环方式转换
  3. [].slice 的方式性能较弱
  4. 最差的就是用 Array.from 进行转换

也可本地进行性能测试,测试代码在 这儿 获取;源码来自 官方提供的 benchmark 示例

因此,如果你想要将 arguments 转换成数组,那么毫无疑问应当使用 ES6 中的 rest 参数转换方式。

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

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

4、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 去测试一下(个人猜测应该结论也差不多)。

5、参考文章


关于 “前端Tips专栏”

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

有两种方式获取历史 tips:

① 在公众号内回 "tips" +"期号" 就可以。例如:回复 “tips25” 即可获取第25期 tips

② 前往网站:https://boycgit.github.io/fe-program-tips,里面提供了搜索功能

欢迎大家关注我的知识专栏,更多内容等你来挖掘

前端Tips#2 - 将 arguments 转换成Array的最佳实践的更多相关文章

  1. 调用短信接口,先var_dump()看数据类型是object需要json_decode(json_encode( $resp),true)转换成array

    返回的数据.先看类型,如果是object类型 先json_encode, 再json_decode,加true 转换成数组 $resp = $c->execute($req); var_dump ...

  2. Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  3. 将arguments转换成数组的方法

    将函数里的arguments,转换成一个真正的数组的方法,arguments是个类数组,除了有实参所组成的类似数组以外,还有自己的属性,如callee,arguments.callee就是当前正在执行 ...

  4. javaScript将string转换成array,并将汉字按汉语拼音排序方法

    亲测,代码如下: var str = '中华人民共和国民主富强': var arr = str.split("");//字符串装换数组方法一 //arr = str.replace ...

  5. C#中服务端接受前端JSON字符串转换成字典集合

    我们是否可以把从前端接受的JSON字符串转换成字典集合呢? 比如从前端接收:{'size':'10', 'weight':'10kg'} 在服务端转换成:[{size:"10"}, ...

  6. 将HTMLCollection/NodeList/伪数组转换成数组

    这里把符合以下条件的对象称为伪数组(ArrayLike) 1,具有length属性 2,按索引方式存储数据 3,不具有数组的push,pop等方法 如 1,function内的arguments . ...

  7. js 判断是否为数组的方式 及 类数组转换成数组格式

    1. 判断是否为数组的通用方式 Object.prototype.toString.call(o)=='[object Array]' 其他方式: typeof ,  instanceof,  ary ...

  8. js 将long型字符串转换成日期格式

    工作中难免会碰到日期的转换,往往为了方便,后台都是把时间以long型(形如1343818800000)返回给web前端.再有前端自己根据页面需求转换成相应的日期格式.这里将我常用的一个转换时间的函数贴 ...

  9. C# Excel转换成Json工具(含源码)

    可执行版本下载:https://github.com/neil3d/excel2json/releases 完整项目源代码下载:https://github.com/neil3d/excel2json ...

随机推荐

  1. spring data jpa 原生sql 别名字段无法注入

    开发四年只会写业务代码,分布式高并发都不会还做程序员?->>>    在使用entityManager.createNativeQuery(sql,User.class)这个方法时, ...

  2. Java练习 SDUT-1140_面向对象程序设计上机练习一(函数重载)

    面向对象程序设计上机练习一(函数重载) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 利用数组和函数重载求5个数最大值 ...

  3. 算法导论笔记:18B树

    磁盘作为辅存,它的容量要比内存大得多,但是速度也要慢许多,下面就是磁盘的的结构图: 磁盘驱动器由一个或多个盘片组成,它们以固定的速度绕着主轴旋转,数据存储于盘片的表面,磁盘驱动器通过磁臂末尾的磁头来读 ...

  4. @uoj - 435@ 【集训队作业2018】Simple Tree

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有一棵有根树,根为 1,点有点权. 现在有 m 次操作,操作有 ...

  5. vue element 中自定义传值

    一直以来都不知道如何传自定义的值,一直只会默认的,今天终于找到方法了. 比如这个上传图片的控件,想带当前的index过去,就这样写.其它的类似 :http-request="(file,fi ...

  6. [***]HZOJ 哪一天她能重回我身边

    %%%神仙题. 居然是图论,我还一直以为是二分图或者啥数据结构. 直接说正解了,将数看作节点,牌看做边,从牌的正面的数想反面连边权为1的边,反面向正面连边权为0的边(注意用到成对存储的技巧,之后会非常 ...

  7. Oracle数据字典全解

    一.概念: 1.数据字典(data dictionary)是 Oracle 数据库的一个重要组成部分,这是一组用于记录数据库信息的只读(read-only)表. 数据字典里存有用户信息.用户的权限信息 ...

  8. oracle 用IN来替换OR

    下面的查询可以被更有效率的语句替换: 低效: SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR     LOC_ID = 20 OR     LOC_ID = 3 ...

  9. 洛谷P1288 取数游戏II 题解 博弈论

    题目链接:https://www.luogu.org/problem/P1288 首先,如果你的一边的边是 \(0\) ,那么你肯定走另一边. 那么你走另一边绝对不能让这条边有剩余,因为这条边有剩余的 ...

  10. PHP利用纯真IP数据库在本地实现IP地址信息查询

    https://blog.csdn.net/myweishanli/article/details/45098693 准备工作: 建议本地IP地址数据库,请到http://www.cz88.net/这 ...