passing a self function as a callback using closure/function binding - javascript

Is it possible to use closure or function binding to pass a self function as an argument for callback from within the function itself?
I used some code to better explain what I'm trying to achieve.
x: function(a, b, c){
if(certain conditions not met){
y(pass function x as argument along with arguments a,b,c for callback);
}
//blah blah
}
y: function(callbackFunc){
//do some stuff
//then execute callback function
callbackFunc();
}

You can define x as a named function, set a flag at if condition to determine whether to pass x or call x to prevent recursive calls to y and x; use Function.prototype.bind() to set this to current or other object, alternate flag at y, call x with y to access original parameters passed to x; optionally pass additional parameters to x.
var obj = {
z: true,
x: function x(a, b, c) {
if (this.z === true) {
this.y(x.bind(this, arguments));
} else {
console.log(arguments, this)
}
//blah blah
},
y: function(callbackFunc) {
//do some stuff
//then execute callback function
if (this.z) {
this.z = false;
// pass additional parameters to `x`
callbackFunc("abc")
};
}
}
obj.x(1, 2, 3);

You can try
x: function(a, b, c){
if(certain conditions not met){
this.y(this.x, a,b,c);
}
//blah blah
}
y: function(callbackFunc,a1,b1,c1){
//do some stuff
//then execute callback function
callbackFunc(a1,b1,c1);
}
I have written a1,b1,c1 just to differenciate, you can use a,b,c

Related

Find which parameters a higher order function contains

I have a function that accepts a function as an argument.
This callback function can receive up to 5 parameters. Any of these can be null at some point.
I tried accessing the arguments property, but it throws this error:
'caller', 'callee', and 'arguments' properties may not be accessed on strict mode.
Is it possible to find which arguments this function received? So i don't have to pass it all 5 each time?
function bar(callback){
// do some stuff
return callback(first, second, third, fourth, fifth)
}
Some use cases I'm having:
bar((a, b, c) => a + c)
bar((a, b, c, d) => a + c + d)
bar((a, b, c, d, e) => a + b + e)
I'm always calling the callback with 5 arguments, but sometimes, not all of them are being used. And for each one, I'm doing some computation.
Another example:
If I call the function like this:
bar((a, b, c, d, e) => a + b + e)
And my function defined like this:
function bar(callback){
// do some stuff with
return callback(first, second, third, fourth, fifth)
}
There would be no need for me to pass the third and fourth parameters to the callback, because they are null. But since I don't have access to the arguments the callback has received, I'm not being able to do this.
You could use Function.length,
function func1() {}
function func2(a, b) {}
console.log(func1.length);
// expected output: 0
console.log(func2.length);
// expected output: 2
But, I would not advice writing code that relies on this. The callback function could be implemented in different ways that this wouldn't work. Some examples:
function callback(){
console.log(arguments); // could access all parameters but length is 0
}
function callback(...args){
console.log(args); // could access all parameters but length is 0
}
function callback(a,b=0,c,d,e){
console.log(a,b,c,d,e); // could access all parameters but length is 1
// 1, only parameters before the first one with
// a default value is counted
}
A better solution would be not overloading the function with different behaviors depending on what the callback expects, and actually tell what you should "return" to the callback
function bar(callback, n){
if(n===0) // do something
else if(n===1) // do something else
}
Or don't write "overloaded" functions that have multiple behaviors, and actually having multiple functions:
function foo(callback){
// do some sutff
return callback(first, second)
}
function bar(callback){
// do some sutff
return callback(first, second, third, fourth, fifth)
}
EDIT: from your last edit you should need to have something like this
function bar(params, callback) {
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5
};
const args = params.map(p => obj[p]);
return callback.apply(this, args);
}
console.log(bar(['a', 'b'], (a, b) => a + b)) //3
console.log(bar(['a', 'd', 'e'], (a, d, e) => a + d + e)) //10
You could take the Function#length property of the function, which returns the number of defined parameters.
function bar(callback) {
console.log(callback.length);
}
bar((a, b) => a + b);
bar(function (a, b, c) { console.log(a, b, c); });

How to pass a function with arguments to a function as argument in javascript? [duplicate]

This question already has answers here:
Passing a function with parameters as a parameter?
(7 answers)
Closed 3 years ago.
I'm new to javascript and I was learning higher-order functions where I learned about passing functions as arguments to other functions. How can I pass a function with arguments to a function?
I want to pass the function's arguments when passing the function as parameter to the main function.
example :
function fubar(a,b,fun(c,d)){
//execute here
}
and not like this
function fubar(a,b,fun()){
fun(a,b)
}
Here's an example, just pass it like a regular argument, no specific syntax is required :)
// define the function argument like a regular argument
function fubar(a, b, fn){
// call that argument like a function
return fn(a, b);
}
// sample function
function add(c, d){
return c + d;
}
// pass the "add" function like a regular argument
let result = fubar(1, 2, add);
console.log(result);
You just need to pass the name of the function as the parameter, just like another variable.
for example :
foobar(5, 10, baz, ham);
function foobar(a, b, fn1, fn2){
...
fn1(); // call the baz function.
res = fn2(a,b); // calls ham func with a and b as parameter
console.log(res)
...
}
function baz(){
console.log("Inside the Baz function ");
}
function ham(s,t){
console.log(s, t);
return s+t;
}
If you're asking how to pass a function that will execute with some pre-determined arguments, you can do so using another function.
For example
const a = 'a'
const b = 'b'
const c = 'c'
const d = 'd'
function fubar(a, b, fn) {
console.info('func:', a, b, fn()) // executing "fn()" here
}
function fun(arg1, arg2) {
console.info('fun:', arg1, arg2)
return 'return value from fun' // just an example so you can see it in fubar()
}
fubar(a, b, () => fun(c, d))
Here, () => fun(c, d) is an self-contained, anonymous arrow function (or "lambda") that when called, will execute fun(c, d).

Javascript: Pass function with arguments as parameter and get this args

I'm trying to write some js function's validation.
Idea: I have checking function, passing to it checked function object, here make sure that all right (or not). I don't want to pass arguments separately, only function object.
How can i reach this?
For now i forced to be content with two parameters for checking function - func obj and func arguments
That is what i want:
function checkFunction(func) {
console.log(func.name);
console.log(func.arguments);
// validate something
}
function checkedFunction(a, b, c) {
checkFunction(checkedFunction...);
// do something
}
That is what i have now:
function checkFunction(func, args) {
console.log(func.name);
console.log(args);
// validate something
}
function checkedFunction(a, b, c) {
checkFunction(checkedFunction, arguments);
// do something;
}

Is it possible to get all defined functions inside other function?

Is it possible inside list to get all available functions - a, b, c without their enumeration and without using window?
(function(){
function a() { return 1; }
function b() { return 2; }
function c() { return 3; }
function list()
{
return [a, b, c];
}
})();
No, it's not possible with functions declared directly in the current scope.
To achieve this, you would have to assign the functions to some property of the scope, i.e.:
(function() {
let funcs = {};
funcs.a = function() {
return 1;
}
...
function list() {
return Object.values(funcs);
}
});
NB: Object.values is ES7, in ES6 use:
return Object.keys(funcs).map(k => funcs[k]);
or in ES2015 or earlier use:
return Object.keys(funcs).map(function(k) { return funcs[k] });
If you haven't even got Object.keys, give up... ;)
I understand where you are trying to get. So perhaps this is the closest thing to what you requested, without using the window name (the same object though):
// define a non-anonymous function in the global scope
// this function contains all the functions you need to enumerate
function non_anon() {
function a() { return 1; }
function b() { return 2; }
function c() { return 3; }
function list() { return [a, b, c]; }
// you need to return your `list` function
// i.e. the one that aggregates all the functions in this scope
return list;
}
// since in here the purpose is to access the global object,
// instead of using the `window` name, you may use `this`
for (var gobj in this) {
// from the global scope print only the objects that matter to you
switch (gobj) {
case 'non_anon':
console.info(gobj, typeof this.gobj);
console.log(
// since you need to execute the function you just found
// together with the function returned by its scope (in order to `list`)
// concatenate its name to a double pair of `()` and...
eval(gobj + '()()') // evil wins
);
break;
}
}

extract parameters from callback outside of the callback

How can I extract the arguments (a, b) of a callback-function and add another
parameter (c) to the function-call?
function mycallback(a, b, c) {
// do stuff with a, b, c
}
function perform(callback) {
// I need to extract a and b here and add c:
// ???
//callback.apply(???);
}
perform( function() { mycallback(1, 2) } );
The only way I can think of is to pass the parameters to perform itself and then let it pass them along to the callback:
function perform(callback) {
var args = Array.prototype.slice.apply(arguments).splice(1);
// use args... add c with args.push(c)...
callback.apply(this, args);
}
perform(mycallback, 1, 2);

Categories