简体   繁体   中英

Javascript functions as Arguments with Arguments

What I want is to load multiple files. These files all use the same function to be loaded, only thing different is the file name. This function should return an object. Something like this:

var files = [ loadFile("file1.txt"), loadFile("file2.txt"), loadFile("file3.txt") ]; 

// Example function
function loadFile( file_name ) {
    return "loaded file " + file_name;
}

But when I run this it loads it directly.

var files = [ loadFile, loadFile, loadFile ];

// now please
for (var i = 0; i < files.length; i++) {
    files[i]();
}

But this way I can't give it arguments. Now I can create a filler function like this, but I there is probably a better way to do this...

function loadFile1() {
    return loadFile( "file1.txt" );
}

If it is possible, how can I load Javascript functions as Arguments with Arguments?

*done some testing. I am going with bind() for the answers, as that is what I was looking for. But I want to mention Stuart's answer that I definitely will keep in mind for the future use. MoeSattler & vlaz thank you guys for showing other good ways of doing this!

Cant you do:

// Example function
function loadFile( file_name ) {
    return "loaded file " + file_name;
}

var files = ["file1.txt", "file2.txt", "file3.txt"]; 
for (i = 0; i < files.length; i++) {
    loadFile(files[i]);
}

How about map ?

 function loadFile( file_name ) { return "loaded file " + file_name; } const fileNames = ['file1.txt', 'file2.txt', 'file3.txt'] const files = fileNames.map(loadFile) console.log(files) 

You could use Function#bind for binding the parameter to the function and call later without parameter.

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

 function loadFile( file_name ) { return "loaded file " + file_name; } var files = [ loadFile.bind(null, "file1.txt"), loadFile.bind(null, "file2.txt"), loadFile.bind(null, "file3.txt") ]; files.forEach(function (a) { console.log(a()); }); 

Option 1 is to use what is called a thunk - it's simply a function that does not take any arguments and returns a value when executed. It's useful for returning something at a later point. You actually do have an example of that with loadFile1 but you can generalise it.

function loadFileLater(fileName) {
    return function() {
        loadFile( fileName );
    }
}

Or using Function.prototype.bind()

function loadFileLater(fileName) {
    return loadFile.bind(null, fileName);
}

Alternatively, you can flip it around and instead of having an array of functions that need values, you can have an array of values where you execute a function against each

 function loadFile( file_name ) { return "loaded file " + file_name; } var filesNames = [ "file1.txt", "file2.txt", "file3.txt", "file4.txt" ] var files = filesNames.map(loadFile) console.log(files); 

In your case, you are most likely going to use .forEach rather than .map but it's the exact same principle.

bind is going to be your best friend here.

Typically bind is used to assign a context to a function (ie: var myBoundFunc = myFunc.bind(myObj) will make sure that any references to this in MyFunc when called via myBoundFunc will point to myObj ), but bind has the added bonus of also being able to store parameters to call myFunc with.

So in your case:

var files = [ loadFile.bind(this, "file1.txt"), loadFile.bind(this, "file2.txt"), loadFile.bind(this, "file3.txt") ]; 

Where this can be any context, and every argument after is used when the resulting function (ie files[0]() ) is called.

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