使用'return'在函数中创建函数是否合适?

Vla*_*iev 4 javascript function

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

function show () {
    return function a() {
        alert('a');
        return function b() {
            alert('b');
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Man*_*rth 10

是的,这有很多用途.

哗众取宠

首先,您可能希望使用currying,其中使用具有多个参数的函数将单个参数封装为函数.例如,

function getHandler(num){
 return function(){
  alert(num);
 }
}

myElement.onclick=getHandler(1)
myOtherElement.onclick=getHandler(25)
anotherElement.onclick=getHandler(42)
Run Code Online (Sandbox Code Playgroud)

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

效率

另一种情况是,当你有一个复杂的函数,它有一个计算重的部分,后面是一个计算轻的部分.这两个部分采用不同的参数,通常第一部分的参数将是相同的.记忆的一些变化可以用来解决这个问题,但函数返回值也可以起作用.

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

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
}
Run Code Online (Sandbox Code Playgroud)

如果我想运行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
 }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

通过闭包的"静态"变量

有时,您希望能够轻松创建一组变量并随身携带.

例如,如果要创建计数器功能:

function generateCounter(){
var c=0;
return function(){
        c++; 
        return c;
       }
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用它来制作许多独立的计数器,例如:

myCtr1=generateCounter();
myCtr2=generateCounter();

myCtr1(); //Returns 1
myCtr1(); //Returns 2
myCtr2(); //Returns 1
myCtr1(); //Returns 3
myCtr2(); //Returns 2
Run Code Online (Sandbox Code Playgroud)

每个柜台都是独立的.当然,在这种情况下,它会更容易使用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;
       }
}
Run Code Online (Sandbox Code Playgroud)

什么时候不应该使用它

每当这样做没有明显的好处时.

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