Javascript - Programmatically execute method on input of all functions - javascript

I would like to add a parser to a list of functions, for example:
var list = {
function1: function(input){},
function2: function(input){}
}
and I would like that all the input params are prepocessed with another function. Is that possible?
Any suggestion?
Thanks in advance

Do you mean something like this? It creates a new copy of funcs with methods that preapply f to their inputs.:
function addPreProcessing(funcs, f) {
return Object.keys(funcs).reduce(function (o, key) {
o[key] = function (input) {
return funcs[key](f(input));
};
return o;
}, {});
}
var list = {
log: function (input) { snippet.log(input); },
quadruple: function (input) { return input * 4; }
};
// preprocess all inputs by doubling them
var list2 = addPreProcessing(list, function (input) {
return input * 2;
});
list2.log(5); // logs 10 ( 5 * 2 )
snippet.log(list2.quadruple(1)); // logs 8 ( 1 * 2 * 4)
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
And here's a lodash version of the addPreProcessing function above:
function addPreProcessing(funcs, f) {
return _.mapValues(funcs, _.flowRight(_.partial(_.flow, f), _.identity));
}

Related

Calling multiple functions with names matching Regex

I have some functions like these:
function name_a(){}
function name_b(){}
function name_x(){}
function name_n(){}
I want to call all functions start with name_ with regex in javascript.
How can I do that?
Just for the kicks, here's something you can use. ES5, so IE>9 is required (could be tweaked for older browsers support, though).
/**
* Calls functions of given target object with names matching given regex.
*
* #param {any} targetObject
* #param {RegExp} nameRegex
* #param {...any} functionsArguments
*
* #returns {any[]} The values returned by each function called.
*/
function callFunctionsMatching(targetObject, nameRegex, functionsArguments) {
// make arguments into array, then splice
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
var functionsArgs = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)).splice(2);
return Object.getOwnPropertyNames(targetObject).filter(function (propertyName) {
return typeof targetObject[propertyName] == 'function' && nameRegex.test(propertyName);
}).map(function (functionName) {
return targetObject[functionName].apply(targetObject, functionsArgs);
});
}
Usage (demo JSBin here)
Global functions (window target object):
// setup some functions
function a1(a, b, c, d) { console.log('a1->', a, b, c, d); }
function b1(arg) { console.log('b1->', arg); }
window.c1 = console.log
// call every function ending with 1
callFunctionsMatching(window, /1$/, 'stuff', 1, 3, 4);
Output:
a1-> stuff 1 3 4
b1-> stuff
stuff 1 3 4
Objects functions (any object as target):
var person = {
aa: function(x) { console.log('person.aa called with', x); return 'this is the return value of person.aa'; },
aaz: function(x) { console.log('I shouldn have been printed'); }
};
var valuesReturned = callFunctionsMatching(person, /aa$/, 'some argument');
console.log('valuesReturned were', valuesReturned);
Output:
person.aa called with some argument
valuesReturned were ["this is the return value of person.aa"]
Example from the question:
function name_a(){ console.log('name_a called'); }
function name_b(){ console.log('name_b called'); }
function name_x(){ console.log('name_x called'); }
function name_n(){ console.log('name_n called'); }
callFunctionsMatching(window, /^name_/, 'args');
Output:
function name_a called
function name_x called
function name_n called
function name_b called
This doesn't handle DOM objects, but if you have a plain object and simply want to search for all the functions matching a certain regex at one level, you could (optionally, showing executing each one in order):
function get_func_filter(obj, match) {
var keys = Object.getOwnPropertyNames(obj);
return keys.filter(function(func_name) {
return typeof obj[func_name] === 'function'
&& match.test(func_name);
});
}
var funcs = {
'prop_a': 'value',
'prop_b': 'value',
'name_a': function(){console.log('name_a function called');},
'name_b': function(){console.log('name_b function called');},
'name_c': function(){console.log('name_c function called');},
'not_name_a': function(){console.log('not_name_a function called');},
'not_name_b': function(){console.log('not_name_b function called');},
};
// First, get the function names that match "starting with name_"
get_func_filter(funcs, /^name_/)
// Then get each name
.map(function(func_name) {
// And execute it (the second)
!funcs[func_name] || funcs[func_name]();
}
);
https://jsfiddle.net/5vrfpmeq/

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);

Inverse of [].filter in JS?

I realize that I can do:
arr = arr.filter(function(n){ return !filterFunc(n); });
But is there any way to just invert a filter without wrapping the filterer in an anon function?
It just seems cumbersome.
You can use an arrow function:
const a = someArr.filter(someFilter);
const a = someArr.filter(e => !someFilter(e));
Lodash provides a reject function that does the exact opposite of filter.
arr = _.reject(arr, filterFunc);
Take a look at lodash's negate function. It does exactly what #Yury Tarabanko mentions in his comment.
Usage:
arr = arr.filter(_.negate(filterFunc));
I wasn't happy with any of the answers directly, and actually wound up using newer JS features
arr.filter(() => ! filterfunc(...arguments));
This beats most of the others by not having to respecify the context (this) at any point by using an arrow function and passing all parameters accordingly using the spread syntax on the arguments object.
It's also rather succinct, though I would rather an invert flag on the filter function, or a separate function.
The question might be a little on the old side, but it's still relevant.
You can either add your own function or add a static/prototype methods to the Array object.
Code
Array Polyfill Methods
/**
* The not() method creates a new array with all elements that fail
* the test implemented by the provided function.
*
* Syntax
* arr.not(callback[, thisArg])
*
* #param callback
* Function to test each element of the array. Invoked with
* arguments (element, index, array). Return true to keep
* the element, false otherwise.
* #param thisArg
* Optional. Value to use as this when executing callback.
* #return Returns a new array containing all the items which fail
* the test.
*/
Array.prototype.not = function(callback) {
return this.filter(function () {
return !callback.apply(this, arguments);
});
};
/**
* Static method which calls Array.prototype.not on the array
* paramater.
*
* #see Array.prototype.not
*/
Array.not = function (array, callback) {
return array != null ? array.not(callback) : [];
};
Custom Function
function unfilter(array, callback) {
return array.filter(function () {
return !callback.apply(this, arguments);
});
}
This is safer to use than a polyfill, but it doesn't look as elegant in use.
unfilter(items, isFruit) vs items.not(isFruit)
Example
// ================================================================
// Polyfill
// ================================================================
Array.prototype.not = function(callback) {
return this.filter(function () {
return !callback.apply(this, arguments);
});
};
// ================================================================
// Main
// ================================================================
var items = [{
name: 'Apple',
isFruit: true
}, {
name: 'Carrot',
isFruit: false
}, {
name: 'Melon',
isFruit: true
}, {
name: 'Potato',
isFruit: false
}];
var isFruit = function(item, index) {
return item != null && item.isFruit;
};
var getName = function(item, index) {
return item != null ? item.name : '?';
};
document.body.innerHTML = items.not(isFruit).map(getName).join(', ');
filter returns elements which return true in your evaluation. If you want to inverse that, inverse your logic it within the function which tests each element.
Then, you could simply make this function work like so:
arr = arr.filter(filterFunc);
There is some ways to do that:
example:
const randomNumbers = [10, 22, 36, 52, 58];
let NewArray = [];
1. Store it in new array:
NewArray = randomNumbers.filter((n)=> ! (n> 22))
2. Using lodash as #Sascha Klatt mentioned above:
NewArray = _.reject(randomNumbers , ((n)=> ! (n> 22)));
3. Make a function like this:
function rejected(params) {
randomNumbers.forEach((val) => {
if (!params(val)) NewArray.push(val);
});
return NewArray;
}
4. or this function (Almost same as above)
function rejected2(params) {
randomNumbers.forEach((val) => {
if (params(val)) {
} else NewArray.push(val);
});
return NewArray;
}
If you really want to do this. You would have to write a helper function that returns a function that returns the inverted value of the normal output.
How you access this function is up to you. But I put in some examples.
Also I'm not saying it is better than writing a custom filter function for each scenario where you need it. You could even use the function you have ( you may or may not want this dependency ).
// APPROACH 1: CREATE A GENERIC HELPER FUNCTION
const arr = [1,2,"a","b"];
function is_a_string( val ) {
return typeof val === 'string';
}
function not( callback ) {
return ( ...arg ) => !callback( ...arg );
}
console.log( arr.filter( not( is_a_string ) ) );
// APPROACH 2: EXTEND A SPECIFIC FUNCTION ( hoisting issue )
const arr = [1,2,"a","b"];
function is_a_string( val ) {
return typeof val === 'string';
}
// note that hoisting is a thing here
is_a_string.not = ( ...args ) => !is_a_string(...args );
console.log( arr.filter( is_a_string.not ) );
// APPROACH 3: CREATE ANOTHER FUNCTION
const arr = [1,2,"a","b"];
function is_a_string( val ) {
return typeof val === 'string';
}
function is_not_a_string( val ) {
return !is_a_string( val );
// or just `return typeof val !== 'string'`; in a simple case like this
}
console.log( arr.filter( is_not_a_string ) );
Lets take an example
var cars = [{
carname: "indica",
brand: "Tata"
},
{
carname: "accord",
brand: "Toyota"
},
{
carname: "vento",
brand: "volkswagen"
},
{
carname: "polo",
brand: "volkswagen"
},
{
carname: "Manza",
brand: "Tata"
},
{
carname: "Agile",
brand: "Chevrolet"
},
];
var isTata = function(car) {
return car.brand === "Tata"
}
var fiteredCars = cars.filter(isTata); // retuns objects of brand Tata
console.log(fiteredCars)
in reverse of this just change your logic
var isNotTata = function(car) {
return car.brand !== "Tata"
}
var dogs = cars.filter(isNotTata); // returns objects of brand other than Tata

Javascript Array of Functions

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();

Functional JavaScript: how to implement Function.prototype.not

I was working on some code earlier today, when I realized, "Hey! This code would be more concise and semantic if I abstracted the idea of a boolean not out of an anonymous function and into a prototype function..."
Consider a predicate generator:
function equalTo(n) {
return function(x) {
return n==x;
};
}
So you can use it like so:
[1,2,3,4,1,2,3,4].filter(equalTo(2)) == [2,2]
Now, my idea is to make a predicate "inverser":
Function.prototype.not = function() {
//???
}
So that you can say:
[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]
My first stab at the implementation was probably very naive:
Function.prototype.not = function () {
return ! this(arguments);
}
And probably why it didn't work.
How would you implement this function, and why?
I'm just trying to wrap my head around functional ideas, and know JavaScript well enough to know it can be used to do this, but just not how.
Your implementation won't work for several reasons:
You need to return a function, not a boolean.
You should pass the arguments as-is, not wrapped in an array.
You should preserve the context (this keyword) that the function would have been called in.
I would implement it like this:
Function.prototype.not = function (context) {
var func = this;
return function() { return !func.apply(context || this, arguments); };
}
I return an anonymous function (function() { ... })
I call apply to call the original function in the current contexts with the actual arguments.
(EDIT) Free bonus: I added an optional context parameter which will override this for the callback.
I would probably do it like so (but perhaps with some sort of namespacing):
function not (x) {
return !x;
}
function id (x) {
return x;
}
function compose (/*funcs*/) {
var args = arguments.length
? Array.prototype.slice.call (arguments)
: [id]
;
return function () {
var val = args [args.length - 1].apply (null, arguments);
for (var i = args.length - 2; i >= 0; --i) {
val = args [i] (val);
}
return val;
};
}
[1,2,3,4,1,2,3,4].filter (compose (not, equalTo (2)));
Using your idea:
function equalTo(n) {
var fn = function(x) {
return n == x;
};
fn.not = function(x) {
return n != x; // use this for simpler conditions
return !fn.apply(this, arguments); // use this for more complex logic
}
return fn;
}
So your example would work:
[1,2,3,4,1,2,3,4].filter(equalTo(2).not) == [1,3,4,1,3,4]
Edit: You can write a helper function (better name to be found) so not doesn't need to be redefined every time:
function generateFnWithNot(fn) {
return function () {
var f = fn.apply(this, arguments);
f.not = function () {
return !f.apply(this, arguments);
}
return f;
};
}
So when you're defining your functions, you can define them as normal with the exception of wrapping a generateFnWithNot call:
var equalTo = generateFnWithNot(function (n) {
return function (x) {
return n == x;
};
});
equalTo(5) // resolves to function () { return n == 5; }
equalTo(5).not // resolves to function () { return n != 5; }

Categories

Resources