Javascript 在javascript中的另一个函数中定义函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10204420/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
define function within another function in javascript
提问by tamakisquare
function foo(a) {
if (/*some condition*/) {
// perform task 1
// perform task 3
}
else {
// perform task 2
// perform task 3
}
}
I have a function whose structure is similar to the above. I want to abstract task 3into a function, bar()
, but I wish to limit the access of this function to only within the scope of foo(a)
.
我有一个函数,其结构与上述类似。我想将任务 3抽象为一个函数,bar()
但我希望将此函数的访问限制在foo(a)
.
To achieve what I want, is it right to change to the following?
为了实现我想要的,更改为以下是否正确?
function foo(a) {
function bar() {
// perform task 3
}
if (/*some condition*/) {
// perform task 1
bar();
}
else {
// perform task 2
bar();
}
}
If the above is correct, does bar()
get redefined every time foo(a)
gets called? (worrying about waste of cpu resource here)
如果以上是正确的,bar()
每次foo(a)
被调用时都会重新定义吗?(担心这里浪费cpu资源)
回答by T.J. Crowder
Yes, what you have there is right. Some notes:
是的,你有什么是对的。一些注意事项:
bar
is created on every call to the functionfoo
, but:- On modern browsers this is a very fast process. (Some engines may well only compile the codefor it once, and then reuse that code with a different context each time; Google's V8 engine [in Chrome and elsewhere] does that in most cases.)
- And depending on what
bar
does, some engines may determine that they can "inline" it, eliminating the function call entirely. V8 does this, and I'm sure it's not the only engine that does. Naturally they can only do this if it doesn't change the behavior of the code.
- The performance impact, if any, of having
bar
created every time will vary widely between JavaScript engines. Ifbar
is trivial, it will vary from undetectable to fairly small. If you're not callingfoo
thousands of times in a row (for instance, from amousemove
handler), I wouldn't worry about it. Even if you are, I'd only worry about it if I saw a problem on slower engines. Here's a test case involving DOM operations, which suggests that there is an impact, but a trivial one (probably washed out by the DOM stuff). Here's a test case doing pure computationwhich shows a much higher impact, but frankly even, we're talking a difference of microseconds because even a 92% increase on something that takes microseconds to happen is still very, very fast. Until/unless you saw a real-world impact, it's not something to worry about. bar
will only be accessible from within the function, and it has access to all variables and arguments for that call to the function. This makes this a very handy pattern.- Note that because you've used a function declaration, it doesn't matter where you put the declaration (top, bottom, or middle — as long as it's at the top level of the function, not inside a flow control statement, which is a syntax error), it gets defined before the first line of step-wise code is run.
bar
在每次调用函数时创建foo
,但是:- 在现代浏览器上,这是一个非常快的过程。(有些引擎可能只为它编译一次代码,然后每次都在不同的上下文中重用该代码;谷歌的 V8 引擎 [在 Chrome 和其他地方] 在大多数情况下都会这样做。)
- 并且根据什么
bar
,某些引擎可能会确定它们可以“内联”它,从而完全消除函数调用。V8 做到了这一点,而且我确信它不是唯一做到这一点的引擎。当然,只有在不改变代码行为的情况下,他们才能做到这一点。
bar
每次创建的性能影响(如果有的话)在 JavaScript 引擎之间会有很大差异。如果bar
是微不足道的,它将从无法检测到相当小。如果您不是foo
连续调用数千次(例如,从mousemove
处理程序中调用),我不会担心。即使你是,我也只会担心如果我看到较慢的引擎有问题。这是一个涉及 DOM 操作的测试用例,它表明存在影响,但影响很小(可能被 DOM 内容冲淡了)。这是一个进行纯计算的测试用例,它显示出更高的影响,但坦率地说,我们正在谈论微秒的差异,因为即使是在需要微秒的事情上增加了 92%发生的秒数仍然非常非常快。直到/除非您看到现实世界的影响,否则无需担心。bar
只能从函数内部访问,并且可以访问该函数调用的所有变量和参数。这使得这是一个非常方便的模式。- 请注意,因为您使用了函数声明,所以将声明放在何处(顶部、底部或中间)并不重要,只要它位于函数的顶层,而不是在流控制语句中,即语法错误),它是在运行第一行逐步代码之前定义的。
回答by Michiel Borkent
This is what closures are for.
这就是闭包的用途。
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 (a closure) holds a reference to bar and only a reference to innerfoo is returned from an anonymous function which is called only once to create the closure.
Innerfoo(一个闭包)持有一个对 bar 的引用,并且只有一个对 innerfoo 的引用从匿名函数返回,该函数只被调用一次来创建闭包。
Bar is not accessible from the outside this way.
酒吧无法通过这种方式从外面进入。
回答by robrich
var foo = (function () {
var bar = function () {
// perform task 3
}
return function (a) {
if (/*some condition*/) {
// perform task 1
bar();
}
else {
// perform task 2
bar();
}
};
}());
The closure keeps the scope of bar()
contained, returning the new function from the self-executing anonymous function sets more visible scope to foo()
. The anonymous self-executing function is run exactly once, so there is only one bar()
instance, and every execution of foo()
will use it.
闭包保持所bar()
包含的范围,从自执行匿名函数返回的新函数将更可见的范围设置为foo()
。匿名自执行函数只运行一次,所以只有一个bar()
实例,每次执行foo()
都会用到它。
回答by Guffa
Yes, that works fine.
是的,这很好用。
The inner function is not recreated each time you enter the outer function, but it's re-assigned.
每次输入外部函数时,内部函数都不会重新创建,而是重新分配。
If you test this code:
如果您测试此代码:
function test() {
function demo() { alert('1'); }
demo();
demo = function() { alert('2'); };
demo();
}
test();
test();
it will show 1
, 2
, 1
, 2
, not 1
, 2
, 2
, 2
.
它会显示1
, 2
, 1
, 2
, not 1
, 2
, 2
, 2
。
回答by Michael Liquori
I created a jsperf to test nested vs. non-nested and function expressions vs. function declarations, and I was surprised to see that the nested test cases performed 20x faster than non-nested. (I anticipated either the opposite or negligible differences).
我创建了一个 jsperf 来测试嵌套与非嵌套以及函数表达式与函数声明,我惊讶地发现嵌套测试用例的执行速度比非嵌套测试快 20 倍。(我预计会有相反的差异或可以忽略不计的差异)。
https://jsperf.com/nested-functions-vs-not-nested-2/1
https://jsperf.com/nested-functions-vs-not-nested-2/1
This is on Chrome 76, macOS.
这是在 Chrome 76、macOS 上。