Javascript Array of Functions - javascript

var array_of_functions = [
first_function('a string'),
second_function('a string'),
third_function('a string'),
forth_function('a string')
]
array_of_functions[0];
That does not work as intended because each function in the array is executed when the array is created.
What is the proper way of executing any function in the array by doing:
array_of_functions[0]; // or, array_of_functions[1] etc.
Thanks!

var array_of_functions = [
first_function,
second_function,
third_function,
forth_function
]
and then when you want to execute a given function in the array:
array_of_functions[0]('a string');

I think this is what the original poster meant to accomplish:
var array_of_functions = [
function() { first_function('a string') },
function() { second_function('a string') },
function() { third_function('a string') },
function() { fourth_function('a string') }
]
for (i = 0; i < array_of_functions.length; i++) {
array_of_functions[i]();
}
Hopefully this will help others (like me 20 minutes ago :-) looking for any hint about how to call JS functions in an array.

Without more detail of what you are trying to accomplish, we are kinda guessing. But you might be able to get away with using object notation to do something like this...
var myFuncs = {
firstFunc: function(string) {
// do something
},
secondFunc: function(string) {
// do something
},
thirdFunc: function(string) {
// do something
}
}
and to call one of them...
myFuncs.firstFunc('a string')

I would complement this thread by posting an easier way to execute various functions within an Array using the shift() Javascript method originally described here
var a = function(){ console.log("this is function: a") }
var b = function(){ console.log("this is function: b") }
var c = function(){ console.log("this is function: c") }
var foo = [a,b,c];
while (foo.length){
foo.shift().call();
}

Or just:
var myFuncs = {
firstFun: function(string) {
// do something
},
secondFunc: function(string) {
// do something
},
thirdFunc: function(string) {
// do something
}
}

It's basically the same as Darin Dimitrov's but it shows how you could use it do dynamically create and store functions and arguments.
I hope it's useful for you :)
var argsContainer = ['hello', 'you', 'there'];
var functionsContainer = [];
for (var i = 0; i < argsContainer.length; i++) {
var currentArg = argsContainer[i];
functionsContainer.push(function(currentArg){
console.log(currentArg);
});
};
for (var i = 0; i < functionsContainer.length; i++) {
functionsContainer[i](argsContainer[i]);
}

up above we saw some with iteration. Let's do the same thing using forEach:
var funcs = [function () {
console.log(1)
},
function () {
console.log(2)
}
];
funcs.forEach(function (func) {
func(); // outputs 1, then 2
});
//for (i = 0; i < funcs.length; i++) funcs[i]();

Ah man there are so many weird answers...
const execute = (fn) => fn()
const arrayOfFunctions = [fn1, fn2, fn3]
const results = arrayOfFunctions.map(execute)
or if you want to sequentially feed each functions result to the next:
compose(fn3, fn2, fn1)
compose is not supported by default, but there are libraries like ramda, lodash, or even redux which provide this tool

This is correct
var array_of_functions = {
"all": function(flag) {
console.log(1+flag);
},
"cic": function(flag) {
console.log(13+flag);
}
};
array_of_functions.all(27);
array_of_functions.cic(7);

If you're doing something like trying to dynamically pass callbacks you could pass a single object as an argument. This gives you much greater control over which functions you want to you execute with any parameter.
function func_one(arg) {
console.log(arg)
};
function func_two(arg) {
console.log(arg+' make this different')
};
var obj = {
callbacks: [func_one, func_two],
params: ["something", "something else"];
};
function doSomething(obj) {
var n = obj.counter
for (n; n < (obj.callbacks.length - obj.len); n++) {
obj.callbacks[n](obj.params[n]);
}
};
obj.counter = 0;
obj.len = 0;
doSomething(obj);
//something
//something else make this different
obj.counter = 1;
obj.len = 0;
doSomething(obj);
//something else make this different

Execution of many functions through an ES6 callback 🤗
const f = (funs) => {
funs().forEach((fun) => fun)
}
f(() => [
console.log(1),
console.log(2),
console.log(3)
])

Using ES6 syntax, if you need a "pipeline" like process where you pass the same object through a series of functions (in my case, a HTML abstract syntax tree), you can use for...of to call each pipe function in a given array:
const setMainElement = require("./set-main-element.js")
const cacheImages = require("./cache-images.js")
const removeElements = require("./remove-elements.js")
let htmlAst = {}
const pipeline = [
setMainElement,
cacheImages,
removeElements,
(htmlAst) => {
// Using a dynamic closure.
},
]
for (const pipe of pipeline) {
pipe(htmlAst)
}

A short way to run 'em all:
[first_function, ..., nth_function].forEach (function(f) {
f('a string');
});

the probleme of these array of function are not in the "array form" but in the way these functions are called... then...
try this.. with a simple eval()...
array_of_function = ["fx1()","fx2()","fx3()",.."fxN()"]
var zzz=[];
for (var i=0; i<array_of_function.length; i++)
{ var zzz += eval( array_of_function[i] ); }
it work's here, where nothing upper was doing the job at home...
hopes it will help

Using Function.prototype.bind()
var array_of_functions = [
first_function.bind(null,'a string'),
second_function.bind(null,'a string'),
third_function.bind(null,'a string'),
forth_function.bind(null,'a string')
]

I have many problems trying to solve this one... tried the obvious, but did not work. It just append an empty function somehow.
array_of_functions.push(function() { first_function('a string') });
I solved it by using an array of strings, and later with eval:
array_of_functions.push("first_function('a string')");
for (var Func of array_of_functions) {
eval(Func);
}

maybe something like this would do the trick:
[f1,f2,f3].map((f) => f('a string'))

Maybe it can helps to someone.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
window.manager = {
curHandler: 0,
handlers : []
};
manager.run = function (n) {
this.handlers[this.curHandler](n);
};
manager.changeHandler = function (n) {
if (n >= this.handlers.length || n < 0) {
throw new Error('n must be from 0 to ' + (this.handlers.length - 1), n);
}
this.curHandler = n;
};
var a = function (n) {
console.log("Handler a. Argument value is " + n);
};
var b = function (n) {
console.log("Handler b. Argument value is " + n);
};
var c = function foo(n) {
for (var i=0; i<n; i++) {
console.log(i);
}
};
manager.handlers.push(a);
manager.handlers.push(b);
manager.handlers.push(c);
</script>
</head>
<body>
<input type="button" onclick="window.manager.run(2)" value="Run handler with parameter 2">
<input type="button" onclick="window.manager.run(4)" value="Run handler with parameter 4">
<p>
<div>
<select name="featured" size="1" id="item1">
<option value="0">First handler</option>
<option value="1">Second handler</option>
<option value="2">Third handler</option>
</select>
<input type="button" onclick="manager.changeHandler(document.getElementById('item1').value);" value="Change handler">
</div>
</p>
</body>
</html>

This answered helped me but I got stuck trying to call each function in my array a few times. So for rookies, here is how to make an array of functions and call one or all of them, a couple different ways.
First we make the array.
let functionsArray = [functionOne, functionTwo, functionThree];
We can call a specific function in the array by using its index in the array (remember 0 is the first function in the array).
functionsArray[0]();
We have to put the parenthesis after because otherwise we are just referencing the function, not calling it.
If you wanted to call all the functions we could use a couple different ways.
For loop
for (let index = 0; index < functionsArray.length; index++) {
functionsArray[index]();
}
Don't forget the parenthesis to actually call the function.
ForEach
ForEach is nice because we don't have to worry about the index, we just get handed each element in the array which we can use. We use it like this (non arrow function example below):
functionsArray.forEach(element => {
element();
});
In a ForEach you can rename element in the above to be whatever you want. Renaming it, and not using arrow functions could look like this:
functionsArray.forEach(
function(funFunctionPassedIn) {
funFunctionPassedIn();
}
);
What about Map?
We shouldn't use Map in this case, since map builds a new array, and using map when we aren't using the returned array is an anti-pattern (bad practice).
We shouldn't be using map if we are not using the array it returns, and/or
we are not returning a value from the callback. Source

I know I am late to the party but here is my opinion
let new_array = [
(data)=>{console.log(data)},
(data)=>{console.log(data+1)},
(data)=>{console.log(data+2)}
]
new_array[0]

you got some top answers above. This is just another version of that.
var dictFun = {
FunOne: function(string) {
console.log("first function");
},
FuncTwo: function(string) {
console.log("second function");
},
FuncThree: function(string) {
console.log("third function");
}
}

/* PlanetGreeter */
class PlanetGreeter {
hello : { () : void; } [] = [];
planet_1 : string = "World";
planet_2 : string = "Mars";
planet_3 : string = "Venus";
planet_4 : string = "Uranus";
planet_5 : string = "Pluto";
constructor() {
this.hello.push( () => { this.greet(this.planet_1); } );
this.hello.push( () => { this.greet(this.planet_2); } );
this.hello.push( () => { this.greet(this.planet_3); } );
this.hello.push( () => { this.greet(this.planet_4); } );
this.hello.push( () => { this.greet(this.planet_5); } );
}
greet(a: string) : void { alert("Hello " + a); }
greetRandomPlanet() : void {
this.hello [ Math.floor( 5 * Math.random() ) ] ();
}
}
new PlanetGreeter().greetRandomPlanet();

Related

Javascript pass variable to function name

I’m trying to create a simple loop of animation functions. I've stored their names in an array and am able to log out each object as a string with a click event. However I can't seem to call the corresponding functions of that event
I've tried to do this but I get an error nt[rt] is not a function
arrAnimations[activeScene]()
I've tried many approaches from stack overflow from similar questions, such as creating a helper function like this
myFunction = function(){};
var arrAnimations = {italy: myFunction};
arrAnimations['activeScene']();//executes the function
and this
var tmp = arrAnimations[activeScene]
window[tmp]
Here is the code:
var arrAnimations = [
'italy',
'czech',
'russia'
]
var activeScene = 0;
document.getElementById('animate').addEventListener("click",
function incNumber() {
if (activeScene < arrAnimations.length - 1) {
activeScene++;
} else if (activeScene = arrAnimations.length - 1) {
activeScene = 0;
}
// console.log(arrAnimations[activeScene])
}
)
function italy() { console.log('italy') }
function czech() { console.log('czech') }
function russia() { console.log('russia') }
<div id="animate">Animate</div>
The array can store the actual functions themselves, instead of the function names.
function italy() { console.log('italy') }
function czech() { console.log('czech') }
function russia() { console.log('russia') }
var arrAnimations = [ italy, czech, russia ]
Then locate the item in the array, and call it:
var activeScene = 0;
arrAnimations[activeScene]()
Demo in Stack Snippets
function italy() { console.log('italy') }
function czech() { console.log('czech') }
function russia() { console.log('russia') }
var arrAnimations = [ italy, czech, russia ]
var index = 0;
function callNextFunction() {
index = index >= arrAnimations.length - 1 ? 0 : index + 1
arrAnimations[index]()
}
var btn = document.getElementById('animate')
btn.addEventListener("click", callNextFunction)
<button id="animate">Animate</button>
In your commented out line:
console.log(arrAnimations[activeScene])
You're trying to call a method on the array, which doesn't exist. It's an array of strings. Instead, you need to get the string value, then use that to call a method on the window.
window[arrAnimations[activeScene]]();
With that said though, I'd make your code a bit simpler and use lambda functions, and avoid a couple of if statements, try this:
<div id="animate">Animate</div>
<script>
var arrAnimations = [
() => console.log('italy'),
() => console.log('czech'),
() => console.log('russia')
]
var activeScene = 0;
document.getElementById('animate').addEventListener('click', () => {
arrAnimations[activeScene]();
activeScene++;
activeScene = activeScene % arrAnimations.length;
});
</script>
italy = () => console.log('italy')
czech = () => console.log('czech')
russia = () => console.log('russia')
if Array of functions:
let arrAnimationsAsFunctions = [ italy , czech , russia];
arrAnimationsAsFunctions.forEach(animation => animation())
if Array of Strings:
let arrAnimationsAsStrings = [ 'italy' , 'czech' , 'russia' ];
arrAnimationsAsStrings.forEach(animation => eval(animation)())
use eval to run a string as JS code
Is this what you want?
foo = () => console.log('foo')
bar = () => console.log('bar')
baz = () => console.log('baz')
fns = {
foo,
bar,
baz
}
Object.keys(fns).forEach(fn => fns[fn]())
fns['foo']()
fns['bar']()
Note: you can't cast a string to a function like this, at least in Javascript:
let fn = () => {}
let foo = 'fn'
foo() // X
// foo is a string, not a function, It is just a coincidence that the content of the string is same with the function's name

Substitute variables in strings like console.log

I want to substitute variables in a string like console.log does.
What I want to achieve is something like this:
let str = 'My %s is %s.';
replaceStr(string, /* args */) {
// I need help with defining this function
};
let newStr = replaceStr(str, 'name', 'Jackie');
console.log(newStr);
// output => My name is Jackie.
/*
This is similar to how console.log does:
// console.log('I\'m %s.', 'Jack');
// => I'm Jack.
*/
I am not able to figure out how to do that. Any help will be much appreciated.
Thank you.
You could prototype it to the String object. Something like this:
String.prototype.sprintf = function() {
var counter = 0;
var args = arguments;
return this.replace(/%s/g, function() {
return args[counter++];
});
};
let str = 'My %s is %s.';
str = str.sprintf('name', 'Alex');
console.log(str); // 'My name is Alex'
You can use spread operator (ES6):
function replaceStr(string, ...placeholders) {
while (placeholders.length > 0) {
string = string.replace('%s', placeholders.shift());
}
return string;
}
EDIT: Based on lexith's answer, we can avoid the explicit loop:
function replaceStr(string, ...placeholders) {
var count = 0;
return string.replace(/%s/g, () => placeholders[count++]);
}
If hope you want to have custom logger function.
console.log can replace %s, with below approach your custom function gets full feature set of console.log and its more efficient.
function myLogger() {
if(logEnabled) {
// you can play with arguments for any customisation's
// arguments[0] is first string
// prepend date in log arguments[0] = (new Date().toString()) + arguments[0] ;
console.log.apply(console, arguments);
}
}
function replaceStr(string, ...placeholders) {
const replaced = string.replace(/%s/g, () => placeholders.shift());
return [replaced, ...placeholders].join(' ');
}
This will append any remaining placeholders to the string to more accurately replicate console.log.

Using a variable as an object and a function

I am trying to mock the times function from the JavaScript library Underscore.js.
This function accepts two syntaxes :
_.times(3, function(n) {
console.log("hello " + n);
});
and
_(3).times(function(n) {
console.log("hello " + n);
});
So far I succeeded to mock the first one by creating an _ object like this :
var _ = {
times: function(reps, iteratee) {
// a loop
}
};
And the second syntax by creating an _ function which returns an object :
function _(n) {
return {
times: function(iteratee) {
// a loop
}
};
}
But I can't use these 2 methods together. I need to find a way that will allow both syntaxes.
Do you have any idea how I could use the _ character as an object as well as a function ?
You should be able to combine two syntaxes like this:
var _ = (function() {
var times = function(n, iteratee) {
// a loop
};
function _(n) {
return {times: function(iteratee) {
return times(n, iteratee);
}}; // or shorter: {times: times.bind(null, n)}
}
_.times = times;
return _;
})();
Here you benefit from the fact that functions are also objects and hence can have properties.
Functions are objects in Javascript, so you could just do something like this:
var _ = function(a,b) { /* ... */ };
_.times = _;
You could extent the function after defining it. Try this:
function _(n) {
return {
times: function(iteratee) {
while (n-- > 0)
iteratee();
}
};
}
_.times = function(reps, iteratee) {
while (reps-- > 0)
iteratee();
};
function iter() {
console.log('iter!');
}
_(3).times(iter);
console.log('----');
_.times(5, iter);

JavaScript (NodeJS) equivalent for PHP's call_user_func_array()

Is there any equivalent function in JavaScript (NodeJS) similar to PHP's
call_user_func_array (http://php.net/manual/en/function.call-user-func-array.php). Which allows to call a function with array of parameters.
In my case, I have to call util.format with parameters that will be in an array.
Here is very simple example trying to show it.
var util = require("util");
function my_fundtion(items) {
var format_string = "";
for (var i=0; i < items.length; i++) {
format_string += " %s";
}
return util.format(format_string, /* here I want to pass items in items array */);
}
PHP has:
call_user_func_array('myfunc', array(1, 2, "foo", false));
While JS has:
myfunc.apply(null, [1, 2, "foo", false]);
The first null goes in the position of an object. You will make use of that if the function is intended to be a method. An example on using such invocation would be to slice array-like objects which are not arrays at all but seem like one (like the arguments object inside of a function):
Array.prototype.slice.apply(arguments, []);
Generally speaking, the syntax is:
(afunction).apply(obj|null, array of arguments)
You can try this:
function my_fundtion(items) {
var format_string = "";
for (var i=0; i < items.length; i++) {
format_string += " %s";
}
var new_items = items.slice();
new_items.unshift(format_string);
return util.format.apply(null, new_items);
}
IMHO that's the wrong approach for a function. Have you tried the following?
function my_fundtion(items) {
return items.join(" ");
}
Because call_user_func_array call function referenced by the function name which is in string. So, in JS we need to use eval.
Example:
const popup = (msg) => {
alert(msg);
}
const subject = {
popup(msg) {
alert(msg);
}
}
So,
eval("popup").apply(null, ['hi'])
eval("subject.popup").apply(null, ['hi'])
Correct me. If i wrong. ;)

How can I call any function in a chain of functions, without the chaining?

Sorry if my question wasn't clear enough. I'll put my code here...
var chain = {
'fn_1' : {
//fn_1 code here
chain.fn_2();},
'fn_2' : {
//fn_2 code here
chain.fn_3();}
...and so on
}
Let's say if i wana call chain.fn_1(), is there a way I can do that without calling chain.fn_2()?
What I can think of right now is a flag, but that would be alot of excess flags probably for each function. Do you guys have any ideas?
If the series of functions each call the next one you're correct, you'd need to have some sort of flag. In all likelihood, what would be best would be to modify your functions so that they return the reference to the object. Then you could chain like so:
var chain = {
'fn_1': function () {
// do something here.
return this;
},
'fn_2': function () {
// do something here.
return this;
},
'fn_3': function () {
// do something here.
return this;
}
};
// call the full chain:
chain.fn_1().fn_2().fn_3();
// call only the middle.
chain.fn_2();
g.d.d.c's answer is best, but if you can't modify the object for some reason, you could do this:
var _oldFn2 = chain.fn_2
chain.fn_2 = function() { return; };
chain.fn_1();
chain.fn_2 = _oldFn2;
var chain = {
fn : ['fn1', 'fn2', 'fn3'],
call : function(name) {
var i = 0, pos = -1, l = this.fn.length;
for(i = 0; i < l; i += 1) {
if(this.fn[i] == name) {
pos = i;
}
if(pos !== -1) {
this[this.fn[i]]();
}
}
},
fn1 : function() {
alert('fn1');
},
fn2 : function() {
alert('fn2');
},
};
chain.call('fn1'); //chain
chain.fn1(); //single

Categories

Resources