前端Tips#2 - 将 arguments 转换成Array的最佳实践
本文同步自 JSCON简时空 - 技术博客,点击阅读
视频讲解
文字讲解
1、先讲结论
有很多种方式将 arguments 转换成数组,那么哪一种方式是最优的?
为节约大伙儿的时间,这里先说一下结论:如果你想将 arguments 转换成数组,最好的方式是使用 rest 参数转换的方式(即使用 ... spread 操作符),比如:
function test(…args) {
console.log(args)
}
test(1,2,3); // [1,2,3]
原因是:性能是 最优 的,可读性也挺好。
想知道为什么的话,可以继续往下看。
2、原因分析
arguments 对象是所有(非箭头)函数中都可用的局部变量,它是一个 “Array-Like” 对象,即 “像数组的对象”的意思,有些文章中也会翻译成 “伪数组对象”。(可以按索引取值、具有 length 属性,但不一定具备 push、concat 等数组方法,具体可参考文章伪数组(ArrayLike)内容)
!> 注意:箭头函数中并不存在 arguments 对象
本期 tip 并不去详细讲 arguments 对象的知识内容(具体知识内容可阅读本讲末尾的参考文章),本讲着重讲解把它转换成数组时的最佳实践。
浏览了许多技术文章,将 arguments 对象转换成数组基本是 4 种方式:
- 使用
Array.prototype.slice.call(arguments)进行转换,或者是使用等效方法[].slice.call(arguments); - 使用
Array.from(arguments)进行转换 - 使用
for循环挨个将arguments对象中的内容复制给新数组中 - 利用 ES6 中的 rest 参数转换,
let a = (...args) => args;
大多数文章也仅仅是讲到这里为止,并没有继续讨论以上哪种方式最优。
接下来我们就用基准测试(Benchmark)的方式来量化上述那种方式性能更好。
3、性能测试
在《做好准备:新的V8即将发布,Node 的性能正在改变》文中给了结论:

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

图中数值越高代表性能越好,以上两幅图所反映的结果是一致的:
- 利用 ES6 中的 rest 参数转换性能最好
- 其次使用
for循环方式转换 [].slice的方式性能较弱- 最差的就是用
Array.from进行转换
也可本地进行性能测试,测试代码在 这儿 获取;源码来自 官方提供的 benchmark 示例
因此,如果你想要将 arguments 转换成数组,那么毫无疑问应当使用 ES6 中的 rest 参数转换方式。
除了性能更好之外,rest 参数的用法相对于直接使用 arguments 还有如下优点:
- 箭头函数和普通函数都可以使用。
- 更加灵活,接收参数的数量完全自定义。
- 可读性更好,参数都是在函数括号中定义的,不会突然出现一个arguments,显得很突兀。
4、Q & A
在这里我简单解答一些常见的疑惑:
Q: 为什么需要将 arguments 对象转换成数组?
A: 答案也简单,因为 Array 实例提供了很多数组方法,比如 .push、.concat 等,提供了更多数据操作方式,归根到底,转换成数组就是为了方便操作数据。
Q: 既然经常要将 arguments 转换成数组,为什么最初不把 arguments 设计成数组格式呢?
A: 按照文章 《JavaScript arguments 对象全面介绍》所言, arguments 在语言的早期就引入了,当时的 Array 对象具有 4 个方法: toString、 join、 reverse 和 sort。arguments 继承于 Object 的很大原因是不需要这四个方法。(当时设计的人也不知道后续的发展会对 arguments 有这方面的强需求...变化无处不在..)
Q: 为什么需要 Array-Like 对象(伪数组对象)的存在?
A: 前面说了,转换成数组也是为了提供更多数据操作方式;其实 Array-Like 对象的存在,也是为了给数据提供更多的操作的可能,因为可以在对象上挂载很多 自定义 的操作方法,使用起来灵活度会很高。
Q: 上述讨论的数组转换结果,是否也适应于其他 “伪数组对象”?
A: 因为 arguments 也是“伪数组对象”,不难推而广之,上面讨论的数组转换的方式都可以应用在“伪数组对象”上;至于每个转换方法的性能如何,我因为没有单独去测试过,所以也不能妄下定论,大家可以自己写 benchmark 去测试一下(个人猜测应该结论也差不多)。
5、参考文章
- 做好准备:新的V8即将发布,Node 的性能正在改变:官方译文,V8 团队新的 JIT 编译器Turbofan 中很多以往的性能问题都获得了解决,推荐阅读;
- V8 性能优化杀手:这篇文章过时了,文中性能优化建议是针对 V8 上一代编译器;之所以还陈列在这儿,是为了方便和上一条参考文章做对比阅读,加深对新 V8 引擎优化的了解。
- arguments is special:arguments 这个变量是特殊的,使用的时候需要多加注意
- JavaScript arguments 对象全面介绍:非常全面的介绍,介绍了它的来历、注意事项
- JavaScript深入之类数组对象与arguments: 本文详细讲解了类数组和 arguments 对象
- 伪数组(ArrayLike):简要介绍了类数组对象的概念和转换;
- JavaScript: arguments leak var array.slice.call?: v8 无法优化 slice 方法的原因,是因为该方法会保持对 arguments 对象的引用,无法将其优化成 stack 变量。
- Array-Like Objects and Generic Methods:犀牛书中对 “伪数组” 概念的解释
- Arraylike的7种实现: 罗列了原生的伪数组列表,同时说明了伪数组出现的缘故 —— 它的出现为一组数据的行为(函数)扩展提供了基础
- JavaScript类数组对象参考:JS 中有哪些伪数组对象?本文给了非常详细的讲解
- 如何创建伪数组:stackoverflow 上关于如何创建伪数组的讨论
- JS Array From an Array-Like Object:本文罗列了将 Array-Like 对象转换成数组的方法,基本就是和本 tip 中罗列的方式差不多
- ES6 系列之箭头函数:本篇重点比较一下箭头函数与普通函数,比较全面
- 详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景:本文这篇文章中还讲了很多 rest 参数的优点
关于 “前端Tips专栏”
“前端Tips”专栏,隶属于是 JSCON 专栏系列,设计初衷是快速获取前端小技巧知识,取材广泛,涵盖前端编程诸多领域。设计初衷是快速消费类知识,所以每个 tips 阅读耗时大约 5 分钟。为方便读者在不同场合阅读,每篇 tips 配有视频、音频和文字,挑自己喜欢方便的就行。
有两种方式获取历史 tips:
① 在公众号内回 "tips" +"期号" 就可以。例如:回复 “tips25” 即可获取第25期 tips
② 前往网站:https://boycgit.github.io/fe-program-tips,里面提供了搜索功能
欢迎大家关注我的知识专栏,更多内容等你来挖掘

前端Tips#2 - 将 arguments 转换成Array的最佳实践的更多相关文章
- 调用短信接口,先var_dump()看数据类型是object需要json_decode(json_encode( $resp),true)转换成array
返回的数据.先看类型,如果是object类型 先json_encode, 再json_decode,加true 转换成数组 $resp = $c->execute($req); var_dump ...
- Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 将arguments转换成数组的方法
将函数里的arguments,转换成一个真正的数组的方法,arguments是个类数组,除了有实参所组成的类似数组以外,还有自己的属性,如callee,arguments.callee就是当前正在执行 ...
- javaScript将string转换成array,并将汉字按汉语拼音排序方法
亲测,代码如下: var str = '中华人民共和国民主富强': var arr = str.split("");//字符串装换数组方法一 //arr = str.replace ...
- C#中服务端接受前端JSON字符串转换成字典集合
我们是否可以把从前端接受的JSON字符串转换成字典集合呢? 比如从前端接收:{'size':'10', 'weight':'10kg'} 在服务端转换成:[{size:"10"}, ...
- 将HTMLCollection/NodeList/伪数组转换成数组
这里把符合以下条件的对象称为伪数组(ArrayLike) 1,具有length属性 2,按索引方式存储数据 3,不具有数组的push,pop等方法 如 1,function内的arguments . ...
- js 判断是否为数组的方式 及 类数组转换成数组格式
1. 判断是否为数组的通用方式 Object.prototype.toString.call(o)=='[object Array]' 其他方式: typeof , instanceof, ary ...
- js 将long型字符串转换成日期格式
工作中难免会碰到日期的转换,往往为了方便,后台都是把时间以long型(形如1343818800000)返回给web前端.再有前端自己根据页面需求转换成相应的日期格式.这里将我常用的一个转换时间的函数贴 ...
- C# Excel转换成Json工具(含源码)
可执行版本下载:https://github.com/neil3d/excel2json/releases 完整项目源代码下载:https://github.com/neil3d/excel2json ...
随机推荐
- 64位Linux编译C代码,crt1.o文件格式不对的问题
今天在某台64位LInux下编译一个简单的hello world的C程序,报错: /usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../crt1.o: cou ...
- C++中文本的读入
读入文本文件 标准库包含逐行读取文本文件的功能.然后,你可以一次一行地解析文本文件的每一行. 比如说,你有文件,其中使用数字和逗号表示一个 3x4 的矩阵: , , , 10.5 , , , , , ...
- offsetheight 和clientheight、scrollheight、scrollTop区别
clientHeight:元素客户区的大小,指的是元素内容及其边框所占据的空间大小(经过实践取出来的大多是视口大小) scrollHeight: 滚动大小,指的是包含滚动内容的元素大小(元素内容的总高 ...
- CDN WAF功能开放公测 提升网络应用安全性能
阿里云CDN WAF功能,是指CDN融合了云盾Web应用防火墙(Web Application Firewall,简称 WAF)能力,在CDN节点上提供安全防护的功能,该功能目前已经开放公测. WAF ...
- HDU3844 Mining Your Own Business
HDU3844 Mining Your Own Business 问题描述John Digger是一个大型illudium phosdex矿的所有者.该矿山由一系列隧道组成,这些隧道在各个大型交叉口相 ...
- Java中Map/List/Set .
很实用,分享一下. 简单版本 复杂版本 参考: http://initbinder.com/articles/cheat-sheet-for-selecting-maplistset-in-java. ...
- oracle函数 ln(y)
[功能]返回以e为底的y的对数(e为数学常量) [参数]y,数字型表达式 (条件y>0) [返回]数字 [示例] select exp(3),exp(-3),ln(20.0855369),ln( ...
- 使用FormData格式上传图像并预览图片
前言 做项目时,遇到表单中图像需要跟表单一起提交,这样会造成后台没办法接收到图片.后面上网调查后,明白表单提交时是默认application/x-www-form-urlencoded格式,只接受键值 ...
- laravel 授权使用gate门类
第一:先注册 第二:使用方式三种 路由中:Route::group(['middleware'=>'can:system'],function() {}) 模板中:@can("syst ...
- canvas+js实现验证码功能
转载自:https://blog.csdn.net/qq_42463851/article/details/90755734<!DOCTYPE html> <html> < ...