4

总结作用域链的概念:

加载网页后,Javascript 会定位函数定义并为每个定义创建一个所谓的变量对象。每个 VO 都必须引用每个局部变量(或全局变量),因此从第一个祖先的函数开始,直到全局上下文。每个函数的作用域链都存储在名为:Scope 的函数属性中。

此外,当调用函数时,会创建一个新对象:一个Activation Object

这是什么?:

它就像一个变量对象(实际上它是一个 VO),负责引用所有函数内部的变量对象,包括“参数”对象和形式参数。

当然,由函数祖先的变量对象+函数的激活对象组成的链中的每一个至少将所有变量映射到undefinedfirst。然后,只要执行进行,它就会通过更新其值(对应于引用的变量)来进化。

但是,我注意到激活对象与变量对象不同,仅仅是因为它包含参数对象,并且这一事实将阻止它在函数被调用之前被创建。

所以,我想知道为什么构建 Javascript 引擎的人没有在函数的定义步骤中分配每个激活对象。因此,当调用函数时,无需创建自己的特定激活对象,因为它已经存在。引擎只会在函数执行结束时清除相应的参数对象,以便下次调用该对象时不会产生副作用。

它可能会提高性能吗?事实上,在每次调用时重新创建一个完整的激活对象可能会消耗......或者这个提议有问题吗?

4

2 回答 2

6

激活对象表示函数调用的上下文。每个调用都必须有自己的对象。它们允许关闭等。

将其视为类似于为调用 C 或 C++ 函数而分配的堆栈帧。

编辑——这是一个示例函数:

function makeCounter( count ) {
  return function() {
    return count++;
  };
}

现在,我可以用它制作一个计数器功能:

var counter1 = makeCounter(1);
alert(counter1()); // alerts "1"
alert(counter1()); // alerts "2"

如果我再做一个呢?

var counter100 = makeCounter(100);
alert(counter100()); // alerts "100"

如果两个调用makeCounter()共享一个arguments实例,当我随后调用“counter1()”时会发生什么?

于 2012-10-30T12:49:28.903 回答
0

You can't have a single Activation Object per function, reused across invocations, because there may be multiple invocations of a function in progress at any given time. One obvious example of this is recursion.

Perhaps you could have, say, 1 eagerly-allocated AO for each function, so at least the first call would be able to use it, but I imagine that kind of mechanism would just complicate the concept for, at best, a nominal performance gain (while also trading off memory).

于 2021-08-18T09:50:36.540 回答