我继续看到:
() => execute code
而不仅仅是
execute code
在回调中。我没有传入任何参数,那么为什么 () => 执行代码有效但执行代码无效?因为一个函数只代表几行代码,所以它们不是一回事吗?我在其他语言中看到类似的东西,比如使用 lambda 的 java
谢谢你。
我继续看到:
() => execute code
而不仅仅是
execute code
在回调中。我没有传入任何参数,那么为什么 () => 执行代码有效但执行代码无效?因为一个函数只代表几行代码,所以它们不是一回事吗?我在其他语言中看到类似的东西,比如使用 lambda 的 java
谢谢你。
使用回调是因为函数需要在未来某个不确定的时间点被调用——代码需要执行。简单地在 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 请求调用。
你看到的是 Javascript 中的一个函数,叫做箭头函数,可以写成如下:
如果返回一个操作,则为单行:
const f = (a,b) => return a+b;
或用于更多操作的行块:
const f = (a,b) => { c = a + b; return c};
区别在于这() => 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
当您将函数定义作为参数传递给函数调用时,您正在使传入的函数定义可用于在被调用函数的主体内访问或调用。
相反,如果您将一个函数调用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.
需要该函数才能知道不应立即执行代码。
如果你会使用
myFunction(myArg, window.location.href='https://www.stackoverflow.com');
代替
myFunction(myArg, () => {
window.location.href='https://www.stackoverflow.com';
});
在第一种情况下,该语言无法知道代码应该在稍后作为回调执行。因此,只要调用该方法就会执行它,这会导致传递布尔值而不是回调函数。在这种情况下,即使调用的函数没有完全运行,页面也会立即打开,而不是在作为回调执行后切换到 stackoverflow.com。
简而言之,传递一个函数允许稍后通过调用它来运行它包含的代码。
通常将带有结果的参数传递给回调以允许处理这些结果。
因为如果你按照你建议的方式去做,代码会立即执行;即当您拨打电话时。
你需要明白这一点
() -> doSomething()
和
doSomething()
意味着不同的事情(以后做与现在做)并评估不同的值。他们甚至没有相同的类型。假设doSomething()
返回SomeType
:
Supplier<SomeType>
lambda 表达式的计算结果为与和兼容的对象SomeType
。我想您认为如果您可以对两种情况使用相同的语法会很好,并让编译器根据上下文确定正确的含义。这有两个问题:
这会使代码更难理解。当您阅读某人的代码时,您需要知道每个表达式的每个参数是否期望具有立即评估语义(如方法调用)或延迟评估语义(如 lambda)的东西。
早在 1960 年代,他们实际上设计并实现了一种像这样工作的编程语言。(查找 Algol-60 并“按名称呼叫”。)这是一个错误。使用名称调用的 Algol-60 程序很难理解。AFAIK,从那时起,任何主流编程语言都没有重复过这个错误。
您仍然需要声明参数是否具有立即或延迟评估语义。我认为不可能推断出方法声明中需要哪个。