返回函数的函数

时间:2011-10-02 23:20:08

标签: javascript

我坚持使用'返回函数的函数'这个概念。我指的是Stoyan Stefanov撰写的“面向对象的Javascript”一书。

Snippet One:

    function a() {
      
        alert('A!');
    
        function b(){
            alert('B!'); 
        }
    
        return b();
    }
    
    var s = a();
    alert('break');
    s();

输出:

A!
B!
break

Snippet Two

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b;
}

var s = a();
alert('break');
s();
输出:

A!
break
B!

有人可以告诉我在上述代码段中返回bb()之间的区别吗?

9 个答案:

答案 0 :(得分:98)

为函数指定变量(不带括号)复制对函数的引用。将括号放在函数名的末尾,调用函数,返回函数返回值。

Demo

function a() {
    alert('A');
}
//alerts 'A', returns undefined

function b() {
    alert('B');
    return a;
}
//alerts 'B', returns function a

function c() {
    alert('C');
    return a();
}
//alerts 'C', alerts 'A', returns undefined

alert("Function 'a' returns " + a());
alert("Function 'b' returns " + b());
alert("Function 'c' returns " + c());

在您的示例中,您还在函数中定义函数。如:

function d() {
    function e() {
        alert('E');
    }
    return e;
}
d()();
//alerts 'E'

该功能仍可调用。它仍然存在。这在JavaScript中一直使用。函数可以像其他值一样在 周围传递。请考虑以下事项:

function counter() {
    var count = 0;
    return function() {
        alert(count++);
    }
}
var count = counter();
count();
count();
count();

函数计数可以保留在其外部定义的变量。这称为闭包。它在JavaScript中也经常使用。

答案 1 :(得分:42)

返回不带()的函数名称会返回对函数的引用,该函数可以像var s = a()一样分配。 s现在包含对函数b()的引用,并且调用s()在功能上等同于调用b()

// Return a reference to the function b().
// In your example, the reference is assigned to var s
return b;

在return语句中使用()调用函数执行函数,并返回函数返回的任何值。它与调用var x = b();类似,但不是指定b()的返回值,而是从调用函数a()返回它。如果函数b()本身没有返回值,则在undefined完成其他任何工作后,调用将返回b()

// Execute function b() and return its value
return b();
// If b() has no return value, this is equivalent to calling b(), followed by
// return undefined;

答案 2 :(得分:29)

return b();调用函数b(),并返回其结果。

return b;返回对函数b的引用,您可以将其存储在变量中以便稍后调用。

答案 3 :(得分:15)

返回b返回一个函数对象。在Javascript中,函数只是对象,就像任何其他对象一样。如果您发现没有帮助,只需将“对象”替换为“对象”即可。您可以从函数返回任何对象。您可以返回true / false值。整数(1,2,3,4 ......)。你可以返回一个字符串。您可以返回具有多个属性的复杂对象。你可以返回一个功能。功能只是一件事。

在你的情况下,返回b返回的东西,东西是一个可调用的函数。返回b()将返回可调用函数返回的值。

考虑以下代码:

function b() {
   return 42;
}

使用上面的定义,return b();返回值42.另一方面,return b;返回一个函数,它本身返回值42.它们是两个不同的东西。

答案 4 :(得分:3)

当你返回b时,它只是对函数b的引用,但此时没有被执行。

当您返回b()时,您正在执行该函数并返回其值。

在示例中尝试alert typeof(s)。代码片段b将为您提供“功能”。会给你什么片段?

答案 5 :(得分:2)

将函数想象为类型,就像int一样。您可以在函数中返回整数。 您也可以返回函数,它们是“函数”类型的对象。

现在语法问题:因为函数返回值,你怎么能返回一个函数而不是它的返回值?

省略括号!因为没有括号,该功能将不会被执行!所以:

return b;

将返回“函数”(想象一下,如果你要返回一个数字),同时:

return b();

首先执行函数然后返回执行它获得的值,这是一个很大的区别!

答案 6 :(得分:2)

创建变量

var thing1 = undefined;

声明功能

function something1 () {
    return "Hi there, I'm number 1!";
}

提醒thing1(我们的第一个变量)的

alert(thing1); // Outputs: "undefined".

现在,如果我们希望thing1成为函数something1引用,意味着它与我们创建的函数相同,我们会这样做:< / p>

thing1 = something1;

但是,如果我们想要函数的return ,那么我们必须为它分配执行函数的返回值。您可以使用括号执行该函数:

thing1 = something1(); // Value of thing1: "Hi there, I'm number 1!" 

答案 7 :(得分:0)

这在现实生活中非常有用。

使用Express.js

因此,您的常规express路线如下所示:

function itWorksHandler( req, res, next ) {
  res.send("It works!");
}

router.get("/check/works", itWorksHandler );

但是如果你需要添加一些包装器,错误处理程序或smth呢?

然后你从包装器中调用你的函数。

function loggingWrapper( req, res, next, yourFunction ) {
  try {
    yourFunction( req, res );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", function( req, res, next ) {
  loggingWrapper( req, res, next, itWorksHandler );
});

看起来很复杂?那么,这个怎么样:

function function loggingWrapper( yourFunction ) => ( req, res, next ) {
  try {
    yourFunction( req, res, next );
  } catch ( err ) {
    console.error( err );
    next( err );
  }
}

router.get("/check/works", loggingWrapper( itWorksHandler ) );

最后看到你传递的函数loggingWrapper有一个参数作为另一个函数itWorksHandler,你的loggingWrapper返回一个以req, res, next为参数的新函数

答案 8 :(得分:-1)

片段一:

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b(); //return nothing here as b not defined a return value
}

var s = a(); //s got nothing assigned as b() and thus a() return nothing.
alert('break');
s(); // s equals nothing so nothing will be executed, JavaScript interpreter will complain

语句'b()'意味着执行名为'b'的函数,该函数显示一个带有文本'B!'的对话框。

语句'return b();'表示执行名为“ b”的函数,然后返回“ b”返回的函数。但是'b'不返回任何内容,因此该语句'return b()'也不返回任何内容。 如果b()返回数字,那么“ return b()”也是数字。

现在's'被赋予返回'a()'的值,该值返回'b()',它什么也不是,所以's'什么都不是(在JavaScript中这实际上是一件事,它是'undefined'因此,当您要求JavaScript解释's'是什么数据类型时,JavaScript解释器会告诉您's'是未定义的。)由于's'是未定义的,因此当您要求JavaScript执行此语句's( )”,您要让JavaScript执行名为“ s”的函数,但是这里的“ s”是“未定义”而不是函数,因此JavaScript会抱怨:“嘿,s不是函数,我不知道”无法知道如何处理此s”,那么JavaScript会显示“未捕获的TypeError:s不是函数”错误消息(在Firefox和Chrome中进行了测试)


第二段

function a() {
  
    alert('A!');

    function b(){
        alert('B!'); 
    }

    return b; //return pointer to function b here
}

var s = a();  //s get the value of pointer to b
alert('break');
s(); // b() function is executed

现在,函数“ a”返回指向名为“ b”的函数的指针/别名。因此,当执行's = a()'时,'s'将获得指向b的值,即's'现在是'b'的别名,调用's'等于调用'b'。即's'现在是一个函数。执行's()'意味着运行功能'b'(与执行'b()'相同),显示“ B!”的对话框将会出现(即运行'alert('B!');函数'b'中的语句)