Search code examples
javascriptnode.jsdecoratorwrapper

JS arguments passed on to function defined after "return" keyword. How does this work?


How are arguments from wrapper functions passed on to functions after the keyword 'return'?

function greeting(name){
    console.log("Hello, " + name)
}


function wrapper(f){
    return function(args){
        
        if(typeof(f)==='function'){
            console.log("before executing wrapped")
            f(args)
            console.log("after executing wrapped")
        }
        else{
            return f
        }        
    }
}

let a = wrapper(greeting)

a("Maria")

So, this works fine, and prints the intended

before executing wrapped
Hello, Maria
after executing wrapped 

because arguments from f are passed on to the line return function(args){ . However, had I not the returnkeyword there, the arguments from fwouldn't have been passed on to the anonymous function. How/why does this happen?

Example of a non-working-version of similar code (only changes to the wrapper function):

function greeting(name){
   console.log("Hello, " + name)
}

function wrapper(f){
   
   if(typeof(f)==='function'){
       
       function a (args){
              
           console.log("before executing wrapped")
           f(args)
           console.log("after executing wrapped")
       }

       return a(args)
   }
   else{
       return f
   }  
}

let a = wrapper(greeting)

a('Maria')

Of course, this returns ReferenceError: args is not defined.

I'm curious to know what's up with the return keyword that makes the first piece of code work.


Solution

  • How can args be identified with 'Maria'?

    The anonymous function in function wrapper, let's name it func1; So the code equals to:

    function wrapper(f){
      function func1(args) {
        // do someting
      }
    
      return func1
    }
    

    let a = wrapper(greeting), actually a is func1;

    Calling a("Maria") is just like calling func1("Maria"), because a is func1. So "Maria" is passed to func1 as the variable args.

    Makes the second code work

    Just return a function(not a function call) in your second code.

    function greeting(name){
       console.log("Hello, " + name)
    }
    
    function wrapper(f){
       
       if(typeof(f)==='function'){
           
           function a (args){
                  
               console.log("before executing wrapped")
               f(args)
               console.log("after executing wrapped")
           }
    
           return a // <--- change at here
       }
       else{
           return f
       }  
    }
    
    let a = wrapper(greeting)
    
    a('Maria')

    Actually, those writing are equivalent:

    function wrapper(f){
        return function(args){
            
            if(typeof(f)==='function'){
                console.log("before executing wrapped")
                f(args)
                console.log("after executing wrapped")
            }
            else{
                return f
            }        
        }
    }
    
    function wrapper(f){
       function a(args){
            
            if(typeof(f)==='function'){
                console.log("before executing wrapped")
                f(args)
                console.log("after executing wrapped")
            }
            else{
                return f
            }        
        }
        return a
    }
    
    function wrapper(f){
       
       if(typeof(f)==='function'){
           
           function a (args){
                  
               console.log("before executing wrapped")
               f(args)
               console.log("after executing wrapped")
           }
    
           return a
       }
       else{
           return f
       }  
    }
    
    function wrapper(f){
       
       if(typeof(f)==='function'){
           
           return function (args){
                  
               console.log("before executing wrapped")
               f(args)
               console.log("after executing wrapped")
           }
       }
       else{
           return f
       }  
    }