javascript函数和参数对象,是否涉及成本
在web和框架中经常可以看到这样的代码:javascript函数和参数对象,是否涉及成本,javascript,performance,Javascript,Performance,在web和框架中经常可以看到这样的代码: var args = Array.prototype.slice.call(arguments); 在这样做的过程中,您可以将参数对象转换为一个真实的数组(就像JS有真实的数组一样),并且它允许应用数组原型中的任何数组方法,等等 我记得在某个地方读到过这样一篇文章:直接访问参数对象可能比数组克隆或命名参数的明显选择要慢得多。这是真的吗?在什么情况下/浏览器会因此受到性能惩罚?你知道有关于这个主题的文章吗 更新有趣的发现使我之前读到的内容无效。。。希望这
var args = Array.prototype.slice.call(arguments);
在这样做的过程中,您可以将参数对象
转换为一个真实的数组
(就像JS有真实的数组一样),并且它允许应用数组原型中的任何数组方法,等等
我记得在某个地方读到过这样一篇文章:直接访问参数
对象可能比数组克隆或命名参数的明显选择要慢得多。这是真的吗?在什么情况下/浏览器会因此受到性能惩罚?你知道有关于这个主题的文章吗
更新有趣的发现使我之前读到的内容无效。。。希望这个问题能从写这篇文章的人那里得到更多的答案
在那一部分的底部写着:
性能神话和真相
始终创建arguments对象
只有两个例外是
将其声明为名称的情况
在一个函数或它的一个函数内部
形式参数。没关系
无论是否使用
这与下列条款相冲突:
然而,使用它不是一个好主意
理由如下:
- 演出
- 保安
参数有两个问题:一个是它不是一个真正的数组。第二个是它只能包含所有参数,包括显式声明的参数。例如:
function f(x, y) {
// arguments also include x and y
}
这可能是最常见的问题,您想要其余的参数,而不需要x
和y
中已有的参数,因此您想要这样的参数:
var rest = arguments.slice(2);
但是不能,因为它没有slice
方法,所以必须手动应用Array.prototype.slice
我必须说,我没有看到仅仅为了性能而将所有参数转换为实际数组,只是为了方便调用数组方法。我必须做一些分析才能知道什么是真正更快的,也可能取决于什么更快,但我的猜测是,如果您不想调用数组方法,那么没有太大的区别,在这种情况下,您别无选择,只能将其转换为实实在在的数组,或者使用call或apply手动应用这些方法
好消息是,在ECMAScript(Harmony?)的新版本中,我们可以编写以下内容:
function f(x, y, ...rest) {
// ...
}
我们将能够忘记所有那些难看的解决办法。一些q&d测试。使用预定义的参数似乎是最快的,但这样做并不总是可行的。如果函数的算术性事先未知(因此,如果函数可以或必须接收可变数量的参数),我认为调用一次Array.prototype.slice
将是最有效的方法,因为在这种情况下,使用参数
对象的代价是最低的。我反对接受的答案。
我编辑了测试,请参见此处:
我添加了对slice
方法的测试和对预分配数组的内存复制的测试。后者在我的电脑中效率要高出数倍。
正如您所看到的,性能测试页面中的前两个内存复制方法速度较慢,这不是因为循环,而是因为push
调用。
总之,切片
似乎是处理参数
的最差方法(不包括推送
方法,因为它们的代码长度甚至不比更有效的预分配方法短得多)。
另外,apply
函数的性能相当好,并且本身不会对性能造成太大影响,这可能会引起人们的兴趣
第一个现有测试:
function f1(){
for(var i = 0, l = arguments.length; i < l; i++){
res.push(arguments[i])
}
}
函数f1(){
for(var i=0,l=arguments.length;i
新增测试:
function f3(){
var len = arguments.length;
res = new Array(len);
for (var i = 0; i < len; i++)
res[i] = arguments[i];
}
function f4(){
res = Array.prototype.slice.call(arguments);
}
function f5_helper(){
res = arguments;
}
function f5(){
f5_helper.apply(null, arguments);
}
function f6_helper(a, b, c, d){
res = [a, b, c, d];
}
function f6(){
f6_helper.apply(null, arguments);
}
函数f3(){
var len=arguments.length;
res=新阵列(len);
对于(变量i=0;i
有一段时间没有人对此进行测试,所有链接都已失效。以下是一些新的结果:
function loop(){
var res = []
for(var i = 0, l = arguments.length; i < l; i++){
res.push(arguments[i])
}
}
function loop_variable(){
var res = []
var args = arguments
for(var i = 0, l = args.length; i < l; i++){
res.push(args[i])
}
return res
}
function slice(){
return Array.prototype.slice.call(arguments);
}
function spread(){
return [...arguments];
}
function do_return(){
return arguments;
}
function literal_spread(){
return [arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9]];
}
函数循环(){
var res=[]
for(var i=0,l=arguments.length;i