Я понимаю семантику, что замыкание содержит ссылку на переменную, удлиняющую ее жизненный цикл, делает примитивные переменные не ограниченными вызовом стека, и, таким образом, эти переменные, захваченные замыканиями, должны быть специально обработаны.
Я также понимаю, что переменные в одной и той же области могут обрабатываться по-разному, в зависимости от того, были ли они захвачены замыканиями в современном движке javascript.например,
function foo(){
var a=2;
var b=new Array(a_very_big_number).join('+');
return function(){
console.log(a);
};
}
var b=foo();
, поскольку никто не хранит ссылку на b
в foo
, нет необходимости хранить b
в памяти, поэтому используемая память может быть освобождена, как только foo
возвращает (или даже никогда не создавался при дальнейшей оптимизации).
Мой вопрос таков: почему v8, по-видимому, упаковывает все переменные, на которые ссылаются все замыкания, вместе в каждом вызывающем контексте?например,
function foo(){
var a=0,b=1,c=2;
var zig=function(){
console.log(a);
};
var zag=function(){
console.log(b);
};
return [zig,zag];
}
и zig
, и zag
, кажется, содержат ссылку на a
и b
, даже если очевидно, что b
недоступен для zig
.Это может быть ужасно, когда b
очень большой, а zig
сохраняется очень долго.
Но стоит с точки зрения реализации, я не могу понять, почему это необходимо.Исходя из моих знаний, без вызова eval
, цепочка областей действия может быть определена до освобождения, таким образом, может быть определена ссылочная связь.Движок должен знать, что когда zig
больше не доступен, то не делайте a
, поэтому двигатель помечает его как мусор.
Кажется, что и chrome, и firefox подчиняются правилу.Стандарт говорит, что любая реализация должна сделать это?Или эта реализация более практичная, более эффективная?Я довольно озадачен.