javascript V8优化和;“泄露论据”;
我在书中读到,建议小心使用javascript V8优化和;“泄露论据”;,javascript,v8,Javascript,V8,我在书中读到,建议小心使用参数对象,这没关系 var i = arguments.length, args = new Array(i); while (i--) args[i] = arguments[i]; 但是,这行不行 function makeArray (l) { var i = l.length, array = new Array(i); while (i--) array[i] = l[i]; return array; }; //..
参数
对象,这没关系
var i = arguments.length, args = new Array(i);
while (i--) args[i] = arguments[i];
但是,这行不行
function makeArray (l) {
var i = l.length, array = new Array(i);
while (i--) array[i] = l[i];
return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
var args = makeArray (arguments);
callback.apply(args[0] = this, args);
};
“泄漏参数”是什么意思?它如何影响优化
我专注于V8,但我认为它也适用于其他编译器
为了证明它有效
函数makeArray(l){
变量i=l.长度,数组=新数组(i);
而(i--)数组[i]=l[i];
返回数组;
};
//...
//编辑:将函数放在对象上,以更好地表示实际情况
var o={};
o、 f=函数(回调){
var args=makeArray(参数);
callback.apply(args[0]=this,args);
};
o、 m=“你好,”;
功能测试(f,n){
警报(此.m+“”+n)
}
o、 f(测试,“它工作…”)
这是一个双重问题:
参数
对象是不可预测的函数a(){返回参数;}
x=a(document.getElementsByTagName('*');
窗口。_interval=setInterval(函数(){
对于(var i=0;i而言,参数的问题与本地eval
和参数的问题相同:它们会导致别名。因此,即使您启用了此类函数的优化,您可能最终也会浪费时间,这是JIT的问题,因为在编译器中花费的时间不是运行代码的时间(尽管优化管道中的某些步骤可以并行运行)
由于参数
泄漏而产生的别名:
function bar(array) {
array[0] = 2;
}
function foo(a) {
a = 1;
bar(arguments);
// logs 2 even though a is local variable assigned to 1
console.log(a);
}
foo(1);
请注意,严格模式消除了这一点:
function bar(array) {
array[0] = 2;
}
function foo(a) {
"use strict";
a = 1;
bar(arguments);
// logs 1 as it should
console.log(a);
}
foo(1);
但是严格模式也没有得到优化,我不知道任何合理的解释,除了基准测试不使用严格模式,而且很少使用严格模式。这可能会改变,因为许多es6功能需要严格模式,所以es6中不需要otoh参数,所以…不会函数a(arg){return arg;}
产生相同的结果?@CoolBlue不,在这种情况下,您返回的是相同的变量。在我的情况下,您一次又一次地返回一个新的参数
对象的引用。@CoolBlue我添加了一个代码来说明我的观点。您可以尝试一下。但要非常小心。您返回的参数
会在中留下一个闭包de>a
和通过参数的循环引用。被调用方
。这是一场内存泄漏完美风暴…我的示例是在makeArray调用中添加对新参数
对象的引用,但在'f``完成后我不会留下任何闭包。我缺少什么?我在示例中没有看到内存泄漏。@CoolBlue我没有看到任何c丢失。并且您的代码仍然有(某种程度上)部分功能与第一个示例相同。您的代码将arguments
对象传递给另一个函数,然后用于调用另一个函数,该函数包含在arguments
对象中,您可以将窗口
对象分配给它。好的,但优化的唯一方法是将while循环置于复制参数
在原始函数中,无法导出它的源代码…对吗?与其使用var o={};o.f=function(){[code]};
,不如使用var o={f:function(){[code]};
。实际上它们是等价的;)是的,它们是。但不同的是,你正在使用我提供的代码创建一个对象,使用一个方法。使用你的代码,你创建一个空对象,然后修改它以插入一个新方法。好吧,最终结果是一样的。我这样做是为了更紧密地模拟我正在分析的实际代码。我知道有几种方法可以但你为什么建议按你建议的方式去做呢?有什么特别的原因吗?我想到了两个好处:1-最基本的是语法本身。你可以在那里声明每个方法和属性,而不需要做任何更改。你不需要到处乱翻来看看方法/属性是如何定义的。2-因为如果您一次完成所有操作,编译器可能会在创建对象和访问任何方法/属性时优化代码。