Why I can't directly set console.log() as callback function

后端 未结 4 1501
遇见更好的自我
遇见更好的自我 2020-12-21 05:47

Why this code doesn\'t work

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

callback(4, console.log(\"Hello         


        
相关标签:
4条回答
  • 2020-12-21 06:10

    If you give the console.log('foo') as a callback you will call the log return as a function.

    A solution is to put your console.log in a function:

    function callback(num, func) {
       for(var i = 0; i < num; i++)
          func();
    }
    callback(4, function(){
       console.log("Hello2")
    });
    
    0 讨论(0)
  • 2020-12-21 06:12

    That's because when you mentioned console.log(), you asked the js engine to evaluate it and it does and passes the result as the 2nd arg to the callback function and not a function object as it expects and hence the call doesn't behave as u desire. The working case correctly passes a function object when u pass a function(){} construct.

    0 讨论(0)
  • Lets step through it to help you visualise what is going on. When the interpreter reads your code, it evaluates function expressions inside-out. That is to say:

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

    A longer-form way of writing this which produces the same outcome would be:

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

    The console.log function doesn't have a defined return value (or at least not a standardised one) - though incidentally all functions in javascript return something - when unspecified this value is literally undefined. So when you run your code you are essentially calling:

    callback(4, undefined);
    

    This means that inside callback, trying to call func as a function will result in:

    TypeError: undefined is not a function

    This is why you need to encapsulate your logic in a new function-closure - whereby func obtains a reference to a callable Function object.


    So How Can I Tidy Up My Code?

    Generally in simple cases like this, what you have done to solve the problem is perfectly acceptable but with more complex logic, you can often end up with several levels of nested callbacks (sometimes referred to as "callback-soup"). To improve readability where code reuse is common you can introduce a function-factory which hides away the nastiness, for example:

    function myLogger(message){
        return function(){
            console.log(message);
        }      
    }
    
    callback(4, myLogger('hello'));
    
    0 讨论(0)
  • 2020-12-21 06:33

    Because functions are first-class citiziens in Javascript (meaning functions can be stored in variables). passing a function as an argument will return a reference to the function definition rather than the function call you're trying to invoke. It does however evaluate your console.log beforehand and passes it on as a variable and since your log's function call doesn't return anything it passes undefined to your callback function.

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

    Is an example of this behaviour. It's also the reason closures like the one demonstrated by Remy J work.

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

    This would work.

    0 讨论(0)
提交回复
热议问题