Reputation: 2189
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!
Upvotes: 1
Views: 140
Reputation: 6904
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)
Upvotes: 3
Reputation: 29007
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.
Upvotes: 2
Reputation: 8136
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.
Upvotes: 1
Reputation: 386578
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 itsthis
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());
});
Upvotes: 2
Reputation: 6795
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]);
}
Upvotes: 6