【问题标题】:Why I can't directly set console.log() as callback function为什么我不能直接将 console.log() 设置为回调函数
【发布时间】:2015-03-28 12:17:35
【问题描述】:

为什么这段代码不起作用

function callback(num, func) {
    for(var i = 0; i < num; i++) {
        func();
    }
}

callback(4, console.log("Hello"));

我知道我必须这样做:

callback(4, function() { console.log("hello"); });

但我仍然不明白为什么我必须这样做。

【问题讨论】:

  • 你在你的 sn-p 中打电话 console.log。而是使用该函数调用的返回值 - 就像在较低的 sn-p 中一样 - 一个匿名函数。
  • 我打赌你使用的是谷歌浏览器?传递 console.log 在其他浏览器中确实有效。

标签: javascript callback this console.log


【解决方案1】:

让我们逐步了解它以帮助您直观地了解正在发生的事情。当解释器读取您的代码时,它会由内而外地评估函数表达式。也就是说:

callback(4, console.log("Hello"));
//          ^------------------^---- is evaluated before "callback" is called.

产生相同结果的更长形式的编写方式是:

var result = console.log("Hello");
callback(4, result);

console.log 函数没有定义的返回值(或至少没有标准化的返回值)——尽管 javascript 中的所有函数都返回 something——当未指定时,这个值实际上是 @987654324 @。因此,当您运行代码时,您实际上是在调用:

callback(4, undefined);

这意味着在callback 内部,尝试将func 作为函数调用会导致:

TypeError: undefined is not a function

这就是为什么您需要将您的逻辑封装在一个新的函数闭包中 - 借此 func 获得对可调用 Function 对象的引用。


那么我该如何整理我的代码?

通常在这样的简单情况下,您为解决问题所做的工作是完全可以接受的,但如果逻辑更复杂,您通常会得到多层嵌套回调(有时称为 "callback-soup ")。为了提高代码重用常见的可读性,您可以引入一个隐藏讨厌的函数工厂,例如:

function myLogger(message){
    return function(){
        console.log(message);
    }      
}

callback(4, myLogger('hello'));

【讨论】:

    【解决方案2】:

    这是因为当您提到 console.log() 时,您要求 js 引擎对其进行评估,它会执行并将结果作为第二个 arg 传递给回调函数,而不是预期的函数对象,因此调用不会不要像你想要的那样行事。 当您传递 function(){} 构造时,工作案例正确地传递了一个函数对象。

    【讨论】:

      【解决方案3】:

      如果您将 console.log('foo') 作为回调,您将调用日志返回作为函数。

      解决方案是将您的 console.log 放入一个函数中:

      function callback(num, func) {
         for(var i = 0; i < num; i++)
            func();
      }
      callback(4, function(){
         console.log("Hello2")
      });
      

      【讨论】:

        【解决方案4】:

        因为函数是 Javascript 中的一等公民(意味着函数可以存储在变量中)。将函数作为参数传递将返回对函数定义的引用,而不是您尝试调用的函数调用。 但是,它确实会事先评估您的 console.log 并将其作为变量传递,并且由于您的日志函数调用不会返回任何未定义的内容,因此它会将未定义的内容传递给您的回调函数。

        function test( logFunction ){
            logFunction( 'test' )
        }
        
        test( alert )
        

        是这种行为的一个例子。这也是 Remy J 所展示的闭包的原因。

        function callback(num, func) {
            for(var i = 0; i < num; i++) {
                func( "Hello" );
            }
        }
        
        callback(4, alert);
        

        这会起作用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-04-10
          • 1970-01-01
          • 1970-01-01
          • 2020-06-09
          • 2015-11-01
          • 2014-08-01
          • 2021-10-30
          相关资源
          最近更新 更多