The Managing arguments
section in Bluebird's article on Optimization killers声明:
arguments
对象不得在任何地方传递或泄露。
换句话说,请勿执行以下操作:
function leaky(){
return arguments;
}
但要这样做:
function not_leaky(){
var i = arguments.length,
args = [];
while(i--) args[i] = arguments[i];
return args;
}
随着Rest paramters的引入,传递rest参数数组会导致优化问题吗?根据我的理解,问题在于我们不能让实际的arguments
对象松散。 arguments
的有限定义副本可以,但不是实际的对象本身。如果是这种情况,那么当以下列方式使用时,rest参数是否被视为arguments
的OK和可优化副本?
function maybe_optimizable(...args){
return args;
}
具体来说,我正在尝试根据David Walsh's debounce
function (which is based on Underscore.js')编写debounce
函数,我认为将arguments
分配给{{debounce
的顶部范围内的变量存在问题。 1}}功能。为了纠正这个问题,我写了以下内容:
function debounce(func, wait, immediate) {
let timeout;
return function (...args) {
let context = this,
now = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(() => {
timeout = null;
if (!immediate) {
func.apply(context, args);
}
}, wait);
if (now) {
func.apply(context, args);
}
};
}
答案 0 :(得分:5)
arguments
对象面临的挑战之一是,它需要是参数值的 live 集合,即使它们被重新分配也是如此。看看具有原始值的(参数)变量如何在没有任何显式赋值的情况下被更改,并且它发生在函数之外:
function modify(arr) {
arr[0] = 3;
}
(function (a) {
console.log('arguments is an ' + arguments.constructor.name);
console.log('a is ', a);
modify(arguments);
console.log('after calling modify, a is ', a);
})(0);

有关此类行为的详情,请参阅this blog。
可以想象,当这样的物体四处移动时,代码优化成为一场噩梦,永远不会失去这种神奇的能力。
当然,这不会发生在普通数组中,并且使用spread语法得到的数组确实是一个普通的数组:
(function (...args) {
console.log('args is an ' + args.constructor.name);
})(0);

您可以放心(没有双关语)确保arguments
提及的代码优化问题不适用于...args
。
正如Bergi所说。当使用arguments
变量的函数以严格模式JavaScript编写时,arguments
的 live 语义不再存在:
function modify(arr) {
arr[0] = 3;
}
(function (a) {
"use strict"; // <-----
console.log('In strict mode');
console.log('arguments is still an ' + arguments.constructor.name);
console.log('a is ', a);
modify(arguments);
console.log('after calling modify, a is still ', a);
})(0);
&#13;
如mdn's article on strict mode中所述:
严格模式代码不包含在其中创建的
arguments
个对象的属性。在第一个参数为arg
的函数中的普通代码中,设置arg
也设置arguments[0]
,反之亦然(除非未提供参数或删除arguments[0]
)。严格模式函数的arguments
对象在调用函数时存储原始参数。arguments[i]
不跟踪相应命名参数的值,命名参数也不跟踪相应arguments[i]
中的值。