var name = function(n) {
var digits = ['one','two','three','four'];
return digits[n];
}
var namenew = (function() {
digits = ['one','two','three','four'];
return function(n) {
return digits[n];
}
}());
两个版本的输出相同,但据说第二个版本比第一个版本快得多。
据我了解,第一个版本每次都会执行该函数,而第二个版本存储执行结果。这就是让我作为功能性/常规 OOPS 程序员感到困惑的原因。
如何保存一个函数及其内部上下文?幕后发生了什么?有人可以澄清一下吗?
最佳答案
该问题的真正答案大约有 3 页长。但我尽量让它尽可能短。 ECMA-/Javascript 都是关于Execution Contexts
和Object
的。 ECMAscript 中的上下文分为三种基本类型:全局上下文
、函数上下文
和eval 上下文
。
每次您调用一个函数时,您的引擎都会在它自己的函数上下文
中生成它。此外,还创建了一个名为 Activation object
的对象。这个神秘对象是 function context
的一部分,它至少包括:
- [[作用域链]]
- 激活对象
- “这个”上下文值
在不同的引擎上可能会有更多的属性,但这三个是任何ES实现所必需的。不过,回到主题。如果调用函数上下文,所有 父上下文
(或更准确地说,父上下文中的 Activation 对象
)都被复制到 [[Scope]]
属性。你可以把这个属性想象成一个数组,里面存放着 (Activation-) 对象。现在,任何与函数相关的信息都存储在 Activation 对象中(形式参数、变量、函数声明)。
在您的示例中,digits
变量存储在 namenew
的激活对象中。第二个是在创建内部匿名函数时,将 Activation 对象
添加到它的 [[Scope]]
属性中。当您在那里调用 digits[n]
时,Javascript 首先尝试在其自己的 Activation 对象中找到该变量。如果失败,则搜索进入 Scopechain。瞧,我们在那里找到了变量,因为我们从外部函数复制了 AO。
为了简短的回答我已经写了太多了,但是要真正很好地回答这样的问题你必须在这里解释一些关于 ES 的基础知识。我想这足以让您了解“幕后”到底发生了什么(还有很多东西需要了解,如果您想阅读更多内容,我会给您一些引用资料)。
你要求它,你得到它:
关于带有闭包的 Javascript 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6614572/