在 JavaScript 函数中使用返回函数和函数作为参数

Using returned functions AND functions as parameters in JavaScript functions

我正在努力思考 JavaScript 中返回的函数和作为参数的函数。到目前为止,我看到一个或另一个在函数中使用,但没有看到两者。我有以下代码:

function adds(num, foo) {
    foo();

    return function(param) {
        document.write("Hello ", param, "<br>");
    };
}

var x = 20;

adds(x, function() {
    x += 2;
})("World");

document.write(x);

//I end up getting:
//Hello World
//22

现在我的问题是,为什么返回的函数先执行?我的理解是,当 adds();被调用它会调用 foo();在返回匿名函数之前。但是,当我们查看输出时情况并非如此。

我也明白这可能不是完成事情的最佳方式,但为了学习,我决定尝试这些概念。

您在使用 x 进行 document.write 调用之前调用了匿名函数。您可以推迟调用该函数以获得您想要的结果。

var result = adds(x, function() {
    x += 2;
});

document.write(x);
result("World");

我已经用显示执行顺序的按顺序编号的注释对您的代码进行了注释。您会注意到从 adds() 返回的回调中的 document.write 在最底部的回调之前被调用。

function adds(num, foo) {
    foo(); // 3. Call anonymous function

    // 5. Return an anonymous function that receives `param` when invoked
    return function(param) {
        document.write("Hello ", param, "<br>"); // 7. Write "Hello " + "World"
    };
}

var x = 20; // 1. Assignment of 20 to `x`

// 2. Call `add()`, passing `20` and an anonymous function
adds(x, function() {

    x += 2; // 4. Mutate `x` to add `2`. This does not affect `num` above.

}) /* 6. Invoke returned anonymous function --> */ ("World");

document.write(x); // 8. Write the current value of `x` (22) to the document

所以你是正确的,传递给 foo 的匿名函数首先被调用,没有让你观察调用的副作用。唯一的副作用是 x 的突变,但直到 document.write() 才可见,它发生在所有其他调用之后。


如果在foo匿名函数中再放一个日志,就可以更清楚地看到它的执行点。

adds(x, function() {
    document.write("Anon func, mutating `x`" + "<br>");
    x += 2;
})("World");

现在输出将是:

Anon func, mutating `x`
Hello World
22

最后说明,使用 console.log()document.write() 更适合观察运行时行为。

在您的初始 adds 函数中

function adds(num, foo) {
    // this occurs on the initial function call, inside the scope of the adds function and does not carry over into the returned function.
    foo();

    // returning your function for later use, this will print 'hello' plus your passed in param.
    return function(param) {
        document.write("Hello ", param, "<br>");
    };
}
// set your initial var
var x = 20;
// execute
adds(x/*20*/, function() {\
    // does not relate to the num param inside the adds function for the return
    x/*20*/ += 2;
})("World");

你的执行顺序不对,为了清楚起见我把事情分解了一些

const adds = (number, callback) => {
  return param => {
    // using callback within scope of returned function
    let x = callback(number);
    document.write(`Hello ${x} ${param}`);
  }
};

let x = 20;
let callbackFunc = amount => (amount + 2);
let results = adds(x, callbackFunc);

对于更实用的现实世界 return 函数,我经常在需要进行一些设置以使回调准备就绪的地方使用它们。这允许您在安装过程中注入依赖项,而不必在所有地方都包含它们。 (帮助解耦测试和组织)

module.exports = function(db,logger) {
    return async (req, res) => {
            let result = await db.findOne(/* stuff */);
            if (result.length === 0) {
                logger.error('stuff not found');
                res.sendStatus(404);
            }
            // do some processing, or not.
            res.send(result);
    };
};