首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >javascript函数和参数对象,是否涉及成本

javascript函数和参数对象,是否涉及成本
EN

Stack Overflow用户
提问于 2011-03-16 20:55:28
回答 3查看 4.2K关注 0票数 18

在web和框架中经常可以看到这样的代码:

var args = Array.prototype.slice.call(arguments);

在这样做的时候,你将参数Object转换成一个实数组(就像JS有实数组一样),它允许你的Array原型中的任何数组方法应用于它,等等。

我记得在某处读到过,直接访问arguments对象可能比数组克隆或明显的命名参数选择慢得多。这是真的吗?在什么情况下/浏览器这样做会导致性能损失?你知道有什么关于这个主题的文章吗?

来自http://bonsaiden.github.com/JavaScript-Garden/#function.argumentsupdate有趣的发现使我之前读到的内容无效...希望这个问题能从写这篇文章的@Ivo Wetzel等人那里得到更多的答案。

在该部分的底部写着:

性能神话和事实

arguments对象总是被创建的,唯一的两个例外是它被声明为函数内部的一个名称或它的一个形参。它是否被使用并不重要。

这与http://www.jspatterns.com/arguments-considered-harmful/相冲突,后者声明:

但是,出于以下原因,使用参数并不是一个好主意:

  • performance
  • security

arguments对象并不是在每次调用函数时自动创建的,如果使用了它,JavaScript引擎只会按需创建它。就性能而言,这种创造并不是免费的。根据浏览器的不同,使用参数和不使用参数之间的差异可能在1.5到4倍之间

显然,不可能两者都是正确的,那么哪一个是正确的呢?

ECMA死硬派Dmitrty Soshnikov说:

“JavaScript engine”到底指的是什么?你从哪里得到这个确切的信息的?尽管在某些实现中这可能是真的(是的,这是一个很好的优化,因为在解析代码时可以获得关于上下文的所有必要信息,所以如果在解析时找不到参数对象,则不需要创建参数对象),但是正如您知道的那样,每次进入执行上下文时,参数对象都会在中创建。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-03-16 22:10:43

Here's一些q&d测试。使用预定义的arguments似乎是最快的,但这样做并不总是可行。如果事先不知道函数的数量(因此,如果函数可以或必须接收可变数量的参数),我认为调用一次Array.prototype.slice将是最有效的方法,因为在这种情况下,使用arguments对象的performance loss是最小的。

票数 4
EN

Stack Overflow用户

发布于 2011-03-16 21:11:56

arguments有两个问题:一个是它不是真正的数组。第二个是它只能包含所有参数,包括显式声明的参数。举个例子:

function f(x, y) {
    // arguments also include x and y
}

这可能是最常见的问题,您希望参数的rest,而不是xy中已有的参数,所以您可能希望有这样的东西:

var rest = arguments.slice(2);

但是您不能这样做,因为它没有slice方法,所以您必须手动应用Array.prototype.slice

我必须说,我还没有看到将所有参数转换为真正的数组仅仅是为了提高性能,只是为了方便调用array方法。我必须做一些分析才能知道哪些方法更快,这也可能取决于哪些方法更快,但我的猜测是,如果您不想调用Array方法,则没有太大区别,在这种情况下,您别无选择,只能将其转换为实际的数组,或者使用call或apply手动应用这些方法。

好消息是,在新版本的ECMAScript中(和谐?)我们将能够编写以下代码:

function f(x, y, ...rest) {
   // ...
}

我们将能够忘记所有这些丑陋的变通方法。

票数 3
EN

Stack Overflow用户

发布于 2015-01-20 04:18:29

我反对这个公认的答案。

我编辑了测试,请看这里:http://jsperf.com/arguments-performance/6

我添加了slice方法的测试和内存复制到预分配数组的测试。在我的电脑上,后者的效率要高出好几倍。

正如您所看到的,该性能测试页面中的前两个内存复制方法速度很慢,不是由于循环,而是由于push调用。

总而言之,slice似乎是使用arguments最糟糕的方法(不包括push方法,因为它们的代码甚至比更有效的预分配方法短不了多少)。

同样有趣的是,apply函数运行得很好,本身没有太多的性能影响。

第一个现有的测试:

function f1(){
    for(var i = 0, l = arguments.length; i < l; i++){
        res.push(arguments[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);
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5325554

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档