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

时间:2017-09-08 20:18:40

标签: javascript function closures anonymous-function

我试图将返回的函数和函数作为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

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

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

3 个答案:

答案 0 :(得分:0)

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

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

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

答案 1 :(得分:0)

我已使用按顺序编号的注释来注释您的代码,这些注释显示了执行顺序。您会注意到document.write返回的回调中的adds()在最底层的回调之前被调用。

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()更适合观察运行时行为。

答案 2 :(得分:0)

在您的初始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);

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

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);
    };
};