为什么回调必须是一个函数?

时间:2019-05-19 05:10:55

标签: javascript callback invocation function-reference

我不断看到:

() => execute code

不只是

execute code 

在回调中。我没有传递任何参数,所以为什么()=>执行代码有效,但是执行代码却无效?因为函数仅代表几行代码,它们不是同一回事吗?我在其他语言以及使用lambda的Java中也看到了类似的情况

谢谢。

5 个答案:

答案 0 :(得分:4)

使用回调是因为需要在将来某个不确定的时刻调用函数-代码需要执行。简单地在javascript中执行代码将始终立即执行它。如果您需要执行一些异步任务并然后执行某些操作,则这无济于事。

例如,setTimeout()进行回调是因为它需要等待,然后然后做一些事情:

//In  about 1500 ms setTimeout will call this ()=>{} function
setTimeout(() => {
  console.log("finished")
}, 1500)

能够传递这样的函数非常灵活,因为该函数还可以接受参数和返回值,这些值可以在调用函数时确定。如果没有将代码组织在一个函数中,那将更加困难,甚至不可能。

如果我只是直接传递一个表达式,它将立即执行:

// console.log runs immediately, there's not way to defer it.
    setTimeout( console.log("finished")
    , 1000)

因此,该函数不仅代表某些代码,还代表可以被称为 的动作。您可以调用它,也可以在特定时间通过setTimeout或HTTP请求之类的其他函数来调用它。

答案 1 :(得分:1)

您看到的是Java语言中的一个函数,称为“箭头函数”,可以编写如下:

如果返回一个操作,则为单行:

const f = (a,b) => return a+b;

或一行代码以进行更多操作:

const f = (a,b) => { c = a + b; return c};

答案 2 :(得分:1)

区别在于() => console.log('execute code')是一个函数定义,而console.log('execute code')是一个函数调用。

在调用该函数之前,函数定义体内的代码不会运行。

var double = (num) => console.log(num + num) // function definition, does nothing

double(2) // function invocation, logs 4 to the console

当您将函数定义作为参数传递给函数调用时,您将使传入的函数定义可在调用的函数体内进行访问或调用。

相反,如果您传递一个函数 invocation ,例如,将double(2)作为另一个函数调用的参数,则您将返回double(2)的返回值(在此示例中,情况undefined,因为console.log没有返回值)在传递给它的函数的主体中可用。

示例:

var double = (num) => console.log(num + num)

var invokeCallbackAfterFiveSeconds = (callback) => {
  setTimeout(callback, 5000);
};

//Passing in a function definition below...

invokeCallbackAfterFiveSeconds(() => double(3));
// ^ Will log 6 to the console after a five second delay


//Passing in a function invocation below...

invokeCallbackAfterFiveSeconds(double(4));
// ^ Will log 8 to the console immediately, then do nothing else.

答案 3 :(得分:0)

该功能是必需的,以便知道不应立即执行代码。
如果您愿意使用

myFunction(myArg, window.location.href='https://www.stackoverflow.com');

代替

myFunction(myArg, () => {   
    window.location.href='https://www.stackoverflow.com';
});

在第一种情况下,该语言无法知道该代码应在以后的某个时刻作为回调执行。 因此,一旦调用方法wich,就会立即执行该操作,从而导致传递布尔布尔值而不是回调函数。在这种情况下,即使调用的函数没有完全运行,也不会立即在执行回调后切换到stackoverflow.com,而是立即打开页面。

简而言之,通过函数可以在以后调用它包含的代码。

通常将带有结果的参数传递给回调,以允许对其进行处理。

答案 4 :(得分:0)

因为如果按照建议的方式进行操作,则代码将立即执行;即当您拨打电话时。

您需要了解

() -> doSomething()

doSomething()

表示不同的事情(以后再做,现在再做),并得出不同的值。他们甚至没有相同的类型。假设doSomething()返回SomeType

  • lambda表达式的计算结果为与Supplier<SomeType>兼容的对象,并且
  • 该调用求值为与SomeType兼容的对象。

我想您认为如果两种情况都可以使用相同的语法,并且让编译器能够根据上下文确定正确的含义,那将很好。这样做有两个问题:

  1. 这将使代码更难理解。当您阅读某人的代码时,您需要知道每个表达式的每个参数是否期望某些具有立即评估语义(例如方法调用)或递延评估语义(例如lambda)的东西。

    在1960年代,他们实际上设计并实现了像这样工作的编程语言。 (查找Algol-60并“按名称呼叫”。)这是一个错误。使用名称呼叫 的Algol-60程序很难理解。 AFAIK,此后此错误在任何主流编程语言中都没有再发生。

  2. 您仍然需要声明参数是具有立即还是延迟的评估语义。我认为不可能推断出方法声明中需要的内容。