简体   繁体   中英

Accept javascript function with parameters, as a parameter (no wrapper)?

Is it possible to write this without the surrounding "wrapper" anonymous function() ? So, basicly turn runner(function(){ myfunction('hello world') }, 'Works!!!') into this runner(myfunction('hello world'), 'Works!!!')

JS

function runner(func, something)
{
    alert(something);
    func();
}


function myfunction(value)
{
    alert("I should execute last!");
}

HTML

<button onclick="javascript: runner(function(){ myfunction('hello world') }, 'Works!!!')">Hit me</button>

JS FIDDLE http://jsfiddle.net/pST95/

It turns out that you can do that after all :-) You can use Function.prototype.bind to create a new function object, with the first parameter as the current context and rest of the arguments as the arguments to the actual function.

function runner(func, something) {
    console.log(something);
    func();
}

function myfunction(value) {
    console.log(value);
    console.log("I should execute last!");
}

runner(myfunction.bind(this, 'hello world'), 'Works!!!')

Output

Works!!!
hello world
I should execute last!

Is it possible to write this without the surrounding "wrapper" anonymous function()?

To have pre-set parameters you'll need to use a wrapper function one way or another. It's convenient to not need to declare it inline, but all solutions will still require that a wrapper function is used.

The ability to pre-set parameters to a function before it's executed is called "Partial Application" . Basically the concept is that you call a function to generate a new function. The new function will call the original function with the correct parameters.

Vanilla JavaScript

Function.prototype.bind allows for additional arguments to be passed after the context which will then be used when the function is eventually called:

runner(myfunction.bind(window, 'hello world'), 'Works!!!');

Of course, IE8 and below don't support this function, so you'll need to use the polyfill to enable this behavior.

jQuery

$.proxy is the cross-browser compatible version in the jQuery library:

runner($.proxy(myfunction, window, 'hello world'), 'Works!!!');

Underscore

_.bind is the cross-browser compatible version in the Underscorejs library:

runner(_.bind(myfunction, window, 'hello world'), 'Works!!!');

however if you want to avoid binding the context when generating the wrapper, underscore also provides a true partial application function.

_.partial will bind the arguments only and allow the context to be determined when the function is executed:

runner(_.partial(myfunction, 'hello world'), 'Works!!!');

What you also can do is use apply or call, so that:

<button onclick="javascript: runner(myfunction,'hello world', 'Works!!!')">Hit me</button>

function runner(func, args, something)
{
    alert(something);
    func.call(this, args);
}

function myfunction(value)
{
    alert("I should execute last!");
}

Your runner function expects a function that takes no arguments because it runs it like this:

func();

So you can't really pass myfunction to it like this:

runner(myfunction, 'Works!!!')

Because you don't have a way to give myfunction an argument (technically it does actually work because your myfunction doesn't use the argument anyway). But if you try this:

runner(myfunction('hello world'), 'Works!!!')

Then all you are doing is calling myfunction directly and sending the returned value (in this case undefined ) as an argument to runner and if you look at the console, you should see an error: TypeError: undefined is not a function

So no, you need the wrapper from your original call or you can use Function.prototype.bind as thefortheye suggested.

how about this

function runner(func, something)
  {
  alert(something);
  eval (func);
  }


function myfunction(value)
  {
  alert("I should execute last!");
  }

runner("myfunction('hello world');", 'Works!!!');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM