TimRGhost February 2016

Invoke a JavaScript function with parameter in a function

Today, I saw the following code below:

log_execution_time = require('./utils').log_execution_time;
var fib = function fib(n) {
    if (n < 2) return n;
    return fib(n - 1) + fib(n - 2);
};

var timed_fib = log_execution_time(fib);
timed_fib(5);

>>> Execution time: 1.166ms

I am curious about function log_execution_time. I don't know how it is.

You can see the input of log_execution_time is a function. How can it call the function with parameter? But all of the methods from w3school need a parameter when calling a function. I assume:

var log_execution_time = function (input_function){
console.time("Execution time");
// input_function
console.timeEnd("Execution time");
}

Thanks and regards

Answers


Dogoku February 2016

I suggest reading up on Functions in Javascript. Here's a nice article from the Mozilla Developer Network (MDN) which is in my opinion, a much better resource than w3schools

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions

To answer your question though, functions in javascript are first class citizens, and what that means is that you can think of them as any other object (string,boolean,number etc). They can be saved in variables and they can be passed as arguments into other functions.

In your example, log_execution_time will actually return a function which is essentially a wrapper around the fib function that gets passed to it


James Thorpe February 2016

This is known as function currying, in this case the function is being curried with a parameter that also happens to be a function. It may look something like this:

function logTime(f) {
    return function() {
        var s = new Date();
        var r = f.apply(null, arguments);
        var e = new Date();
        console.log('Time taken ' + (e-s));
        return r;
    }
}

function numberlogger(n) {
    console.log("logged number: " + n)
};

var timedlogger = logTime(numberlogger);

console.log(timedlogger(2));

We call logTime, passing in numberlogger as an argument. Functions in JavaScript are objects and can be passed around like anything else. The logTime function returns a different function that is then stored in timedlogger. When we invoke timedlogger, we're actually invoking the function that logTime returned. That uses a couple of variables to keep track of the start and end times for timing, but uses apply (which every function in js has) to call the original function (numberlogger) whilst passing in any arguments supplied.


Paul S. February 2016

I think the OP is specifically about how the 5 parameter gets passed to the function input_function

Functions are first class objects in JavaScript. You can set identifiers and pass their references around just the same as any other object.

  1. log_execution_time(fib); does not invoke fib, it passes a reference to fib into the log_execution_time function as the first argument. This means the internals can reference fib
  2. timed_fib is a function which can reference the closure from that invocation of log_execution_time due to when it was created, so it can hence invoke the reference to fib as desired

Here is a simple example;

function log(msg) {
    console.log(msg);
}

function wrap(fn) {
    return function () { // some anonymous function to be our wrapper
        console.log('Wrapped:');
        fn.apply(this, arguments); // this line invokes `fn` with whatever arguments 
                                   // that were passed into the anonymous function
    };
}

var foo = wrap(log);
foo('Hello World'); // logs
// Wrapped:
// Hello World

We could also have used the more usual way to invoke fn, for example fn("fizz buzz");, instead of .apply but that would mean we needed to know more about how to invoke fn, which could have been anything


Useful stuff:

  • Function.prototype.apply
  • nAviD February 2016

    The code can be like this:

    var log_execution_time = function (input_function){
    var f=function(args)
    {
         var t1=new Date().getTime();
         input_function(arguments);
         console.warn("Execution time:" +(new Date().getTime()-t1).toString());
    }
    return f;
    }
    

Post Status

Asked in February 2016
Viewed 1,123 times
Voted 11
Answered 4 times

Search




Leave an answer