1

i'm trying to input a function into another function and then running it.

I have a function.

function example_function() {
    document.print('example')

and I would like to input into another function to have it executed N times.

function do_n_times(function, times) {
    for (var i = times; i < times; i++) {
        do(function)
    }
}

Is there a way to do this, and if so. Can you also do custom inputs?

function do_n_times_with_this_input(function, times, input) {
    for (var i = times; i < times; i++) {
        do(function(input))
    }
}
  • 5
    Yes, this would work. To call a function, you just append `()` at the end of it, so if you have a parameter `fn` you'd call it via `fn()`. And if you want to supply any input, then `fn(input)`. You have to get rid of `do` and change the parameter's name from `function` to something that's not a reserved word and you're done. – VLAZ Apr 02 '20 at 18:26
  • as @VLAZ comments, `function` is a reserved word of javascript, you can just change to another like func fn or another word, and to call it just func() with () at the end of parameter name for function you want to execute. – Eric Ocampo Apr 02 '20 at 18:47
  • Hello, if your issue was resolved by the below answer, consider marking as accepted by clicking the grey tick next to it :) – Anurag Srivastava Apr 15 '20 at 21:08

2 Answers2

1

You can absolutely do this! JavaScript has what's called first-class functions, which means they can be passed around just like any other variable. The syntax for that looks like this:

function example_function() {
  console.log('example')
}

function do_n_times(func, times) {
  for (var i = 0; i < times; i++) {
    func();
  }
}

do_n_times(example_function, 5);
Hamms
  • 4,416
  • 17
  • 27
0

Yes, you can do what you describe. In JavaScript, you can call any variable as a function by appending () at the end:

function f1() {
  console.log("f1 called")
}

const f2 = () => console.log("f2 called");

const nonFn = 42;

f1();
f2();

try {
  nonFn();
} catch (e) {
  console.log("Error because nonFn is not a function")
}

You can further pass functions in any way you want:

function f1() {
  console.log("f1 called")
}

const f2 = () => console.log("f2 called");

function caller(fn) {
  fn();
}

caller(f1);
caller(f2);
caller(() => console.log("directly defined arrow function called"));
caller(function() { console.log("directly defined normal function called"); });

Which also means that you can pass any input you want as well:

function f1(input) {
  console.log("f1 called with", input)
}

const f2 = input => console.log("f2 called with", input);

function caller(fn, input) {
  fn(input);
}

caller(f1, "foo");
caller(f2, "bar");
caller(
  input => console.log("directly defined arrow function called with", input),
  "baz"
);
caller(
  function(input) { console.log("directly defined normal function called with", input); },
  "quux"
);

This is the basic stuff, you can have more control over how you execute a function by using Function#call and Function#apply. In both cases that allows you to execute a function and change its context

function f() {
  console.log("f called with context:", this);
}

function caller(fn) {
  const newContext = {foo: "hello"}
  fn.call(newContext);
}

function applier(fn) {
  const newContext = {bar: "world"}
  fn.apply(newContext);
}

caller(f);
applier(f);

You can also pass arguments in both cases. The difference between .call() and .apply() is in what form you pass them. And if you don't care about the context (the function is not using this) then you can just use null as the argument for that:

function f(a, b, c) {
  console.log(
    "f called with arguments",
      "\n\ta:", a,
      "\n\tb:", b,
      "\n\tc:", c
  );
}

function caller(fn, a, b, c) {
  fn.call(null, a, b, c);
}

function applier(fn, a, b, c) {
  fn.apply(null, [a, b, c]);
}

caller(f, "passed", "directly", "into");
applier(f, "passed", "as", "array");

The difference seems negligible but here is a real good use-case for .apply - you can supply infinite arguments to a function:

function f(...args) {
  console.log(
    "f called with arguments:", args
  );
}

function applier(fn) {
  const argumentsForFunction = Array.prototype.slice.call(arguments, 1);
  fn.apply(null, argumentsForFunction);
}

applier(f, "one");
applier(f, "alpha", "beta", "gamma");
applier(f, "a", "b", "c", "d", "e", "f", "g");

Notice how Array#slice was called with the arguments object in order to exclude the first item (the function) and take the rest.

You can get quite a lot of control over how a function is executed. using these.

A final option is Function#bind - it works a lot like call in that you can change the context and pass arguments but the difference is that it returns a new function that will always use these. This has useful applications - you can permanently set this so you never "loose" it.

Another useful application of the .bind() method is creating called "partially applied function" - this is a function that normally takes multiple parameters but you've permanently set some of them, so the function only waits for the remaining ones or even just for execution:

function f(a, b) {
  console.log(
    "f called with arguments",
      "\n\ta:", a,
      "\n\tb:", b
  );
}
//null for the context - we don't care for it here
const f1 = f.bind(null, "hello");

f1("world");
f1("my baby");
f1("my honey");

const f2 = f1.bind(null, "my ragtime gal");

f2();
VLAZ
  • 18,437
  • 8
  • 35
  • 54