2

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

TimRGhost
  • 33
  • 2
  • 1
    You can pass functions as stand-alone un-invokes object or _anonymous functions_ (other languages call this LAMBDAS). All you need to do with a passed function is invoke it with its variable name. So this would work: `function exec(a){ a(); } exec( function(){ alert('Anonymous but still alerting!'); } );`. Read up on the basics of `functions` before continuing, heres a link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions – somethinghere Feb 08 '16 at 17:14
  • Functions are first class objects in _JavaScript_. You can set identifiers and pass their references around just the same as any other object. `log_execution_time(fib);` does not invoke `fib`, it passes a reference to `fib` into the `log_execution_time` function as the first argument – Paul S. Feb 08 '16 at 17:16

4 Answers4

1

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.

James Thorpe
  • 31,411
  • 5
  • 72
  • 93
  • 1
    @DavinTryon No, [it seems to work without doing so](https://jsfiddle.net/yug06q3y/) (at least in chrome) – James Thorpe Feb 08 '16 at 17:26
  • 1
    If you are talking about `Array.prototyle.slice`, then no. Slice will only convert the arguments object to an array, but `apply` will happily take the arguments object from another function – Dogoku Feb 08 '16 at 17:26
1

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:

Community
  • 1
  • 1
Paul S.
  • 64,864
  • 9
  • 122
  • 138
0

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

Dogoku
  • 4,585
  • 3
  • 24
  • 34
0

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;
}
nAviD
  • 2,784
  • 1
  • 33
  • 54