众所周知,在JavaScript中使用arguments
不当可能会导致函数无法优化(请参阅here和here by the end):
function notOptimisable (a, b) {
// Optimising compiler says: Nope.
var args = [].slice.call(arguments)
}
然而,到目前为止,没有一个消息来源设法解释为什么这会阻止优化发生。
它更令人难以置信,因为我所要做的就是
function optimisable (a, b) {
// Optimising compiler says: I can do this!
var args = new Array(arguments.length)
, i = 0
// Copy the arguments into an actual array, very carefully...
for(i; i < args.length; ++i)
args[i] = arguments[i]
}
和voilá - 我有arguments
的副本,它是一个实际数组,可以优化该功能:
node --trace_opt --trace_deopt script.js # Exerpt below
[marking 0x24ba2c0bf0f1 <JS Function notoptimisable (SharedFunctionInfo 0x26b62a724859)> for recompilation, reason: small function, ICs with typeinfo: 3/3 (100%), generic ICs: 0/3 (0%)]
[disabled optimization for 0x26b62a724859 <SharedFunctionInfo notoptimisable>, reason: Bad value context for arguments value]
[failed to optimize notoptimisable: Bad value context for arguments value]
[marking 0x24ba2d0041b1 <JS Function optimisable (SharedFunctionInfo 0x26b62a7247b1)> for recompilation, reason: small function, ICs with typeinfo: 7/7 (100%), generic ICs: 0/7 (0%)]
[optimizing 0x24ba2d0041b1 <JS Function optimisable (SharedFunctionInfo 0x26b62a7247b1)> - took 0.039, 0.164, 0.051 ms]
因此,我问你:
arguments
只是语言设计视角中的“类似数组”对象(即它有数字键,但它不是数组的后代)并且以某种方式播放在优化过程中的作用?答案 0 :(得分:6)
没有不可克服的技术挑战。这只是在Crankshaft中实现arguments对象时做出的快捷决策:仅支持可以轻松避免参数对象实现的情况。
即使Crankshaft支持参数对象的实现,结果代码仍然会比不分配参数对象的代码慢。
这只是在10分钟内支持最快案例而不是在10天内支持更慢但更通用的案例的问题。 (10分钟/ 10天是虚数,我只想传达实现复杂程度的差异)。
如果想要支持参数对象实现(并且可能泄漏)的情况,那么需要考虑参数对象和参数之间的别名 - 这会改变如何为这些变量构造SSA表单。由于类似的原因,这也使内联复杂化。
参数对象的更通用的方法应该基于转义分析/分配下沉传递 - 但Crankshaft在实现时没有类似的东西,它仍然需要至少支持一些参数操作的快速路径。
答案 1 :(得分:2)
arguments
不是数组,例如,考虑:
function abc(a) {
arguments[0] = 1;
console.log(a);
}
abc(0);
这里的问题是arguments[0] = 1
的分配神奇地改变了a
的值,I.E。 arguments[0]
aliases a
。它是eval
和with
导致的同一问题 - 您无法再静态地查看更改的变量以及何时更改。
在strict mode
下删除了混淆错误,没有技术上的理由说明为什么这不会被优化,但是它可能被认为是不值得的,因为大多数网络都没有首先使用严格模式或删除它以获取生产代码。
答案 2 :(得分:1)
原因可能是因为JavaScript没有实现传统意义上的实际数组。数组更像是具有length属性的JavaScript对象,即{}
。 arguments
不是Array
的事实是该语言中的设计错误。这可能是优化器出现问题的原因。