在javascript中定义另一个函数中的函数
function foo(a) { if (/*some condition*/) { // perform task 1 // perform task 3 } else { // perform task 2 // perform task 3 } }
我有一个function,其结构类似于上面。 我想把任务3抽象成一个函数bar()
,但是我想限制这个函数的访问只在foo(a)
的范围内。
为了达到我想要的目的,是否可以改为如下?
function foo(a) { function bar() { // perform task 3 } if (/*some condition*/) { // perform task 1 bar(); } else { // perform task 2 bar(); } }
如果以上是正确的,每当foo(a)
被调用时bar()
被重新定义? (担心在这里浪费CPU资源)
是的,你有什么是对的。 一些说明:
- 每次调用该函数时都会创build一个
bar
,但是:- 在现代浏览器上,这是一个非常快的过程。 (有些引擎可能只编译一次代码 ,然后每次使用不同的上下文; Google的V8引擎(在Chrome和其他地方)在大多数情况下都是这样做的。
- 而且,根据
bar
不同,一些引擎可能会确定它们可以“内联”,从而完全消除函数调用。 V8做到这一点,我相信这不是唯一的引擎。 当然,如果它不改变代码的行为,他们只能这样做。
- JavaScript引擎对性能的影响,如果有的话,每次都会有不同的创build。 如果
bar
是微不足道的,它会从不可察觉到相当小。 如果你不是连续调用数千次(例如,从一个mousemove
处理程序),我不会担心它。 即使你是,我只会担心,如果我看到一个慢引擎问题。 下面是一个涉及DOM操作的testing案例 ,它暗示了一个影响,但却是一个微不足道的(可能被DOM的东西冲昏了头脑)。 这里有一个testing用例 ,它对纯粹的计算performance出了更高的影响,但坦率地说,我们所说的微秒差异是因为即使是需要微秒的事情发生的时间增加了92%仍然是非常快的。 直到/除非你看到真实世界的影响,这是不值得担心的。 -
bar
只能从函数内访问,并且可以访问该函数调用的所有variables和参数。 这使得这是一个非常方便的模式。 - 请注意,因为您使用了函数声明 ,所以放置声明的位置并不重要(上,下或中间 – 只要它位于函数的顶层,而不在stream控制语句中一个语法错误),它在第一行逐步代码运行之前被定义。
var foo = (function () { var bar = function () { // perform task 3 } return function (a) { if (/*some condition*/) { // perform task 1 bar(); } else { // perform task 2 bar(); } }; }());
闭包保持bar()
包含的范围,从自执行的匿名函数返回新函数将更多的可见范围设置为foo()
。 匿名自执行函数只运行一次,所以只有一个bar()
实例,并且foo()
每个执行都会使用它。
这是closures的目的。
var foo = (function () { function bar() { // perform task 3 }; function innerfoo (a) { if (/* some cond */ ) { // perform task 1 bar(); } else { // perform task 2 bar(); } } return innerfoo; })();
Innerfoo(一个闭包)拥有一个对bar的引用,并且只有一个被称为innerfoo的引用被从一个仅被调用一次的匿名函数返回来创build闭包。
酒吧不能从外面访问这种方式。
是的,这工作正常。
每次input外部函数时都不会重新创build内部函数,但会重新分配内部函数。
如果你testing这个代码:
function test() { function demo() { alert('1'); } demo(); demo = function() { alert('2'); }; demo(); } test(); test();
它会显示2
,而不是2
。