【问题标题】:Using returned functions AND functions as parameters in JavaScript functions在 JavaScript 函数中使用返回函数和函数作为参数
【发布时间】:2018-02-17 19:44:56
【问题描述】:

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

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

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

【问题讨论】:

  • 您希望发生什么?

标签: javascript function closures anonymous-function


【解决方案1】:

我已经用顺序编号的 cmets 对您的代码进行了注释,这些 cmets 显示了执行的顺序。您会注意到从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");

现在输出将是:

匿名函数,变异`x` 你好世界 22

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

【讨论】:

  • 现在说得通了,谢谢!我唯一的另一个问题是您所说的:// 4. 这不影响上面的num 是什么意思。 ?
  • @TroyLeu:很高兴它有帮助。我的意思是,当您将x 传递给adds 函数的num 参数,然后改变x 的值时,x 的突变不会也改变num。例如,如果您从adds 返回的回调也写入num 的值,即使x 更改为22,它仍会写入20
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-19
      • 1970-01-01
      • 2010-10-14
      • 2011-08-30
      • 2019-10-11
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      相关资源
      最近更新 更多