使用'return'在函数中创建函数是否合适?(Is it good to make function in function using 'return'?)

当我调查功能时,我意识到我可以创建嵌入式功能。 首先,我认为它可能对构造代码很有用。 但现在我认为这不是好的编码风格。 我对吗? 这是一个例子。

function show () { return function a() { alert('a'); return function b() { alert('b'); } } }

我可以使用这个字符串调用alert('b') : show()() ;

在什么情况下最好使用这种方法,而不是什么?

While I was investigating functions, I realised that I can create embedded functions. Firstly, I thought it may be useful for structuring code. But now I suppose it isn't good style of coding. Am I right? Here is an example.

function show () { return function a() { alert('a'); return function b() { alert('b'); } } }

And I can call alert('b') using this string: show()();

In what situations is better to use this method and in what not?

最满意答案

是的,这有很多用途。

哗众取宠

首先,您可能想要使用currying ,在其中使用带有多个参数的函数的单个参数封装函数。 例如,

function getHandler(num){ return function(){ alert(num); } } myElement.onclick=getHandler(1) myOtherElement.onclick=getHandler(25) anotherElement.onclick=getHandler(42)

onclick()不能被赋予任意参数,因为它被系统调用。 不是编写3个警告不同数字的不同处理程序,而是通过创建一个可以生成“警告数字”类型的任意处理程序的函数来减少膨胀。 当然,这是一个相当简单的例子,但是如果必须做一些比alert()更复杂的事情,那么currying的好处是显而易见的。

效率

另一种情况是,当你有一个复杂的函数时,有一个计算重量较大的部分,后面跟着一个计算光部分。 这两个部分采用不同的参数,通常第一部分的参数将是相同的。 memoization的一些变化可以用来解决这个问题,但函数返回值也起作用。

例如,假设您具有以下形式的功能:

function doSomething(a,b,c,x,y){ //Do some complicated calculations using a,b,c, the results go to variables e,f,g //Do some simple calculations using e,f,g,x,y, return result }

如果我想运行doSomething(1,2,3,18,34)+doSomething(1,2,3,55,35)+doSomething(1,2,3,19,12) ,则需要运行3次执行时间为长整数每次执行。

但是,我们可以将其写为:

function doSomethingCreator(a,b,c){ //Do some complicated calculations using a,b,c, the results go to variables e,f,g return function(x,y){ //Do some simple calculations using e,f,g,x,y, return result } }

现在,我需要做的就是为我的参数集调用doSomethingCreator() ,并使用创建的函数(这很快)来获得最终结果。 代码变成:

var doSomething123=doSomethingCreator(1,2,3); console.log(doSomething123(18,34)+doSomething123(55,35)+doSomething123(19,12))

其中一个例子就是求解微分方程。 如果给出一些“边界条件”,微分方程就没有单一解。 然而,(特别是对于均匀方程),在一点后很容易改变边界条件并得到解。 通常需要多次为不同的边界条件求解相同的方程。 因此,如果你想编写一个库方法,你可以将同质方程作为输入,并且它将返回一个函数,而这又可以给出边界条件作为输入以获得最终解。

“静态”变量通过闭包

有时候,您希望能够轻松创建一组变量并将它们带到身边。

例如,如果你想创建一个计数器函数:

function generateCounter(){ var c=0; return function(){ c++; return c; } }

我们可以用它来创建许多独立的计数器,例如:

myCtr1=generateCounter(); myCtr2=generateCounter(); myCtr1(); //Returns 1 myCtr1(); //Returns 2 myCtr2(); //Returns 1 myCtr1(); //Returns 3 myCtr2(); //Returns 2

每个柜台都是独立的。 当然,在这种情况下,使用myCtr1=0;myCtr2=0然后使用++运算符会更容易,但是如果你想记录它们递增的时间怎么办? 扩展++情况会涉及很多代码重复,但是,在这里我们可以很容易地调整它:

function generateCounter(){ var c=[]; // The length of c is the value of the counter return function(){ c.push((new Date()).getTime()); return c; } }

当你不应该使用它

每当这样做没有明显的收获。

除了想要将它用于闭包变量时,使用外部函数的0参数通常没有多大意义,因为内部函数变成了相同的函数。 看看它是否真的改善了程序,然后使用它。

Yes, this has many uses.

Currying

Firstly, you may want to use currying, where you encapsulate a function with a single argument with a function with many arguments. For example,

function getHandler(num){ return function(){ alert(num); } } myElement.onclick=getHandler(1) myOtherElement.onclick=getHandler(25) anotherElement.onclick=getHandler(42)

onclick() cannot be given arbitrary arguments as it is called by the system. Instead of writing 3 different handlers that alert different numbers, this reduces the bloat by creating a function that can generate arbitrary handlers of the "alert a number" type. Of course, this is a rather simplistic example, but if one had to do something considerably more complicated than alert(), the benefits of currying are evident.

Efficiency

Another situation is when you have a complicated function that has one computationally-heavy portion, which is followed by a computationally-light portion. The two portions take different parameters, and usually the parameters for the first portion will be the same. Some variation of memoization can be used to solve this, but function-as-return value works too.

For example, let's say you have a function of the following form:

function doSomething(a,b,c,x,y){ //Do some complicated calculations using a,b,c, the results go to variables e,f,g //Do some simple calculations using e,f,g,x,y, return result }

If I want to run doSomething(1,2,3,18,34)+doSomething(1,2,3,55,35)+doSomething(1,2,3,19,12), it would take 3 times the execution time as the long part is execute every time.

However, we can write it as:

function doSomethingCreator(a,b,c){ //Do some complicated calculations using a,b,c, the results go to variables e,f,g return function(x,y){ //Do some simple calculations using e,f,g,x,y, return result } }

Now, all I need to do is call doSomethingCreator() for my set of parameters, and use the created function (which is fast) to get the final results. The code becomes:

var doSomething123=doSomethingCreator(1,2,3); console.log(doSomething123(18,34)+doSomething123(55,35)+doSomething123(19,12))

One example of this is solving differential equations. Differential equations do not have a single solution if some "boundary conditions" are given. However, (especially for homogenous equations), after one point it is easy to vary the boundary conditions and get solutions. And usually one needs to solve the same equation for different boundary conditions multiple times. So, if you want to write a library method, you would have it take the homogenous equation as the input, and it would return a function, which in turn can be given the boundary conditions as an input to get the final solution.

"Static" variables via closures

Sometimes, you want to be able to easily create a set of variables and carry them around.

For example, if you want to create a counter function:

function generateCounter(){ var c=0; return function(){ c++; return c; } }

We can use this to make many independent counters, for example:

myCtr1=generateCounter(); myCtr2=generateCounter(); myCtr1(); //Returns 1 myCtr1(); //Returns 2 myCtr2(); //Returns 1 myCtr1(); //Returns 3 myCtr2(); //Returns 2

Each counter is independent. Of course, in this case, it would be easier to jut use myCtr1=0;myCtr2=0 and then the ++ operator, but what if you want to record the times when they were incremented? Extending the ++ case would involve a lot of code duplication, however, here we can tweak it pretty easily:

function generateCounter(){ var c=[]; // The length of c is the value of the counter return function(){ c.push((new Date()).getTime()); return c; } }

When you should not use it

Whenever there is no obvious gain in doing so.

Aside from when you want to use it for closure-bound variables, there usually isn't much point in doing it with 0 arguments for the outer function as the inner function becomes the same function. See if it really improves the program, and then use it.

更多推荐