Use function declaration passed as an argument - javascript

I am trying to create a stub definition that the code below could use:
func.calc({
'divide': function(num1, num2) {
// do something
},
'add': function(num1, num2, num3) {
// do something
}
});
So far, I've been having trouble getting the parameters passed to the functions in the second argument. Here's what I've been trying to do:
var func = {
calc: function(operationsArray) {
if (div) {
operationsArray[0](args); /* get args */
}
else (add) {
operationsArray[1](args); /* get args */
}
}
}
Is it possible to get the whole function definition (with parameters and implementation) when it is passed as a parameter like in the first snippet?

You're declaring func.temp as method that accepts an Array as second argument. On the other hand, you call the method with an Object as the second argument.
JavaScript specification tells us that field order is not guaranteed:
4.3.3 Object
An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.
meaning you shouldn't access in_func & in_func2 using location index (i.e. [0]).
You should either call the function with an array like this:
func.temp(mainArg, [
function(arg1, arg2) {
// do something
},
function(arg1, arg2, arg3) {
// do something
}
]);
OR, implement the function so that it uses explicit names:
var func = {
temp: function(arg1, func_obj) {
// do something with arg1
if (trigger1) {
func_obj.in_func(/* get params */);
}
else (trigger2) {
func_obj.in_func2(/* get params */);
}
}
}

Related

How to use 2 arguments in a 1-arg javascript function?

I am using the http module in node.js to read from url. The http.get function has this signature:
http.get(options[, callback])
The callback function takes a single argument, res. What can I do if I want to use extra objects/functions inside the callback? I can think of inlining the get call like so:
outerFunction = function(xyz) {
http.get(options, (res) => {
// do stuff with xyz here
xyz(res.blah);
}
});
But if my callback gets long I want to declare it upfront somewhere:
myCallback = function(xyz) {
return function(r) { xyz(r.blah); };
}
And invoke myCallback like so:
outerFunction = function(xyz) {
http.get(options, (res) => {
myCallback(xyz)(res);
});
}
But that seems super clumsy and only to get around the 1-arg callback restriction.
Are there better ways? Thanks!
you can use this code please,because myCallback return a function,then after get the resource,http will pass the res into xyz automatically.
outerFunction = function(xyz) {
http.get(options,myCallback(xyz));
}
You could use the arguments object.
The arguments object is a local variable available within all
functions. You can refer to a function's arguments within the function
by using the arguments object. This object contains an entry for each
argument passed to the function, the first entry's index starting at
0.
Quick example:
function test1234(a){
var args = arguments;
console.log(args); // prints -> 0: "a", 1: "b"
}
test1234('a', 'b');

ES6 default values not available in function.arguments?

If I have this ES6 function declaration and invocation:
function myFunction (arg1, arg2 = "bob") {
console.log("arguments", arguments);
}
myFunction(1);
...the console.log() statement shows only one argument with a value of "1". "bob" is nowhere to be seen. Is this expected and/or desired behavior? I would expect that default values would be available in the arguments object. If not, is there a way to dynamically get all arguments + defaults in some other manner?
Thanks in advance!
Yes, this is expected and desired. The arguments object is a list of the values that were passed into the function, nothing else.
It is not implicily linked to the parameter variables (that get assigned the default values), like it was in sloppy mode.
Is there a way to dynamically get all arguments + defaults in some other manner?
No. What parameters you have and whether they have default initialisers is static, you don't need to do anything here dynamically. You can do Object.assign([], arguments, [arg1, arg2]) for your example function.
As you know by now, there is no native method to get both "passed arguments AND defaults where arguments are not passed". But there is a workaround:
This function (that I found here) gets all parameters of a given function:
function getArgs(func) {
var args = func.toString().match(/function\s.*?\(([^)]*)\)/)[1];
return args.split(',').map(function(arg) {
return arg.replace(/\/\*.*\*\//, '').trim();
}).filter(function(arg) {
return arg;
});
};
So, combining this function with the arguments of your function myFunction, we can get an array that has what you want:
function myFunction (arg1, arg2 = "bob") {
var thisArguments = arguments;
console.log(getArgs(myFunction, thisArguments));
};
function getArgs(func, argums) {
var args = func.toString().match(/function\s.*?\(([^)]*)\)/)[1];
var argsArray = args.split(',').map(function(arg) {
return arg.replace(/\/\*.*\*\//, '').trim();
}).filter(function(arg) {
return arg;
});
for(var i = 0; i < argsArray.length; i++){
argsArray[i] += " (default)";
}
var defaults = argsArray.slice(argums.length);
argums = Array.prototype.slice.call(argums);
return argums.concat(defaults);
};
Now, we can see the information in the console calling myFunction:
1. Passing more arguments than parameters
This will return only the arguments.
myFunction("foo", "bar", "baz");
//returns: ["foo", "bar", "baz"]
2. Passing less arguments than parameters
Will return the arguments and the remainder parameters as default, as you want (I added "default" to each string).
myFunction("foo");
//returns ["foo", "arg2 = "bob" (default)"]
3. Passing no arguments
This will return all the parameters.
myFunction();
//returns ["arg1 (default)", "arg2 = "bob" (default)"]
This is the fiddle: https://jsfiddle.net/gerardofurtado/25jxrkm8/1/

Slice JS function's arguments

I want to write a common confirm method like
var confirmDelete = function (fun) {
if (confirm("Do you want to delete " + arguments[1])) {
$(arguments[2]).remove();
fun(arguments[3]);
}
return false;
}
It's working fine for fun with one parameter, but I want to suit for two or more parameters, how I can do it?
every javascript Function object has a method named apply. apply will call your function using the given context and the given arguments.
var confirmDelete=function(fun) {
if(confirm("Do you want to delete "+ arguments[1])) {
// remove the first two elements in arguments, and use the resulting array as a new set of
// arguments to fun
fun.apply(this, Array.slice(arguments, 2));
}
}
In JavaScript you can pass as many parameters as you want.
If you don't pass them, they will be undefined.
So... You can do something like this:
var confirmDelete = function(arg1, arg2, arg3) {
if (typeof arg2 === 'undefined') {
arg2 = "default value for arg2";
}
if (typeof arg3 === 'undefined') {
arg3 = "default value for arg3";
}
// do more stuff...
}
You can also read about the magical arguments variable here.
You can rewrite your function something like
var confirmDelete = function fun(arg1, arg2) {
// number of parameter as your need
// TODO some stuff
fun(arg1 -1, arg2 +3); // call it recursively
return false;
}

Modifying callback function's argument(s) before calling them

I have a custom object that implements a function that'll be executed later. Here's how someone would call it:
customObject.onSomething(function(e) {
// do something with e
console.log('foobar');
});
Here's how onSomething is getting created:
var CustomObject = function() {
this.onSomething = function(callback) {
// If the user passes in parameter(s), how can I modify them before calling?
callback.apply(this);
}
}
How can I modify the argument(s) the user passed in before performing apply or call on the function?
apply takes a second parameter which is a list of arguments to pass to the function. call does the same, except it passes its own argument-list (everything after the first parameter which is used as this).
So, if you know which parameters you expect, you can just add them to the invoking function as the second parameter to apply (or as a list of parameters to call):
this.onSomething = function(arg1, arg2) {
// reverse the first and second arguments
callback.apply(this, [arg2, arg1]);
// equivalent:
callback.call(this, arg2, arg1);
};
If you don't know what kind of arguments to expect, but you still want to do something with them, you can do so with the builtin arguments pseudo-array which holds the arguments given to the current function (even when you don't declare them explicitly).
You can use this to invoke the callback with the same arguments given to the invoking function, or some transformation of them; e.g.:
this.onSomething = function() {
// call callback with the same arguments we got
callback.apply(this, arguments);
// or, make some changes
var newArgs = ["extra argument", arguments[1], arguments[0]];
callback.apply(this, newArgs);
};
Sounds like what you're asking for is fairly simple, see below:
var CustomObject = function() {
this.onSomething = function(callback, param1, param2) {
param1 += 4;
param2 = 'Something about ' + param2 + ' is different...';
callback.apply(this, [param1, param2]);
}
}

Javascript - Pass variable parameters to Function

I am looking to be able to create two functions, BaseFunction and CallbackFunction where BaseFunction takes in a variable set of parameters as such:
BaseFunction(arg1, arg2, ....)
{
//Call the Callback function here
}
and callback function receives the same parameters back:
CallbackFunction(value, arg1, arg2, ...)
{
}
How can I pass the parameters from the base function to the callback function?
Use apply to call a function with an array of parameters.
BaseFunction(arg1, arg2, ....)
{
// converts arguments to real array
var args = Array.prototype.slice.call(arguments);
var value = 2; // the "value" param of callback
args.unshift(value); // add value to the array with the others
CallbackFunction.apply(null, args); // call the function
}
DEMO: http://jsfiddle.net/pYUfG/
For more info on the arguments value, look at mozilla's docs.
to pass arbitrary number of arguments:
function BaseFunction() {
CallbackFunction.apply( {}, Array.prototype.slice.call( arguments ) );
}
This kind of does the trick:
BaseFunction(arg1, arg2, ....)
{
CallbackFunction(value, arguments);
}
However CallbackFunction needs to accept array:
CallbackFunction(value, argsArray)
{
//...
}

Categories