Passing arbitrary number of parameter to a function in javascript - javascript

I would like to write a javascript function that works something like this...
f([["a"]], function(e){alert(e);});
// results in alert("a");
f([["a"], ["b"]], function(e1,e2){alert(e1 + ":" + e2);});
//results in alert("a:b");
f([["a", "b"], ["c"]], function(e1,e2){alert(e1 + ":" + e2);});
//results in alert("a:c");alert("b:c");
I can think of a recursive solution for the looping, but how do I send a "unknown" number of variables to a function?

If you put all your arguments into an array (lets call it foo), you can call a function fn with those arguments by using the apply-function.
fn.apply(null, foo)
The first argument (null in this case) is whatever you want this to be inside of the called function. null will probably work for you.

According to this page, you can access any/all arguments using the arguments variable:
function f() {
for( var i = 0; i < arguments.length; i++ ) {
//do something with arguments[i]
}
}
[EDIT]
Now that I understand what you're trying to do, here's a (dirty) way to do it:
Seriously, don't do it this way. It's horrible. Puppies will die.
function f(arr, fn) {
var s = "fn(";
for( var i = 0; i < arr.length; i++ ) {
//you can implement your recursive code here if you like; I'm just doing the base cases
s += arr[i];
if(i+1 < arr.length) {
s += ",";
}
}
s += ");";
eval(s);
}
And for a cleaner way:
function f(arr, fn) {
fn.apply(this, arr);
}

Within the function you can use the variable arguments to see what was passed. IE
function blah() {
console.log(arguments);
}
blah(1, 2); // [1, 2]
blah([1, 2], [3]); // [[1,2], [3]]
blah(1, [2, 3], "string"); // [1, [2, 3], "string"]

You can use the arguments variable that each function has to go through all the passed in arguments.
function myConcat(separator) {
var result = ""; // initialize list
// iterate through arguments
for (var i = 1; i < arguments.length; i++) {
result += arguments[i] + separator;
}
return result;
}
See this article for a discussion of variable number of arguments.

You can use the arguments pseudo-array available within the function to get the arguments passed in without declaring them explicitly (i,e. regardless of whether you define an argument for a function, you can access everything passed in to the function via the arguments implicit variable within that function).

Related

Javascript Filter Function in a For Loop

I was able to complete the task using .filter() and a For Loop, but not sure why I cannot use the format in my second example. First example works fine.
function destroyer(arr) {
for(i=1; i < arguments.length; i++){
number = arguments[i];
arr = arr.filter(function(num){
return num !== number;
});
}
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
Tried to replace the return num !== number; with return num!==arguments[i] but the arguments[i] does not appear to return the numeric value.
Because arguments refers to a different functions arguments at that point.
Every time you enter a function, arguments will refer to the currently executing functions arguments. It wouldn't make much sense for arguments to only refer to the top-level functions arguments.
Example:
function a() {
console.log(arguments[0]);
var b = function() {
console.log(arguments[0]);
};
b('This is b');
}
a('This is a');

How a function got passed to another function?

I came across a weird code which I didn't understood. It would be great if I get explanation.
function forEach(array, action) {
for (var i = 0; i < array.length; i++) {
action(array[i]);
}
}
var numbers = [1, 2, 3, 4, 5], sum = 0;
forEach(numbers, function (number) {
sum += number;
});
console.log(sum);
How the function got passed as parameter ? and how the inner function is getting that number.
In JavaScript, functions are what's called first class citizens (that's not necessarily true for other languages), that means that functions can be treated as data, you can pass functions as arguments, return functions from other functions, and create functions and assign them to variables.
Here's a very simple example:
function callWithoutParams(fn) {
return fn(); // fn is the passed function.
}
let rand = callWithoutParams(Math.random); // Passing Math.random as a function.
callWithoutParams(() => console.log(42)); // Passing anonymous function
Array.prototype.forEach() accepts a function as an argument, and runs it on each element in the array. So a simpler example is:
[1,2,3,4,5].forEach((element) => console.log(element)); // outputs 1-5 in order.
In javascript, everything is an object, including function.
For simplicity, check this example:
var func = function(number){
console.log(number);
}
var arr = [1,2,3,4,5];
function foreach(data, callback){
for(var i = 0; i<data.length; i++){
callback(data[i]);
}
}
foreach(arr, func);
In JS, you can assign function to a variable. This is called as Function Expression. So it acts as a normal variable, just that its type is object.
This allows us to pass function as a parameter.
Now your second question, how the inner function is getting that number.
in your code, action(array[i]); is passing value as a parameter, so
function (number) {
sum += number;
}
here number is array[i].

How is passing an anonymous function as an argument internally used?

I've encountered some code that I'm having trouble fully understanding. The principles seem clear enough, but I'm having some difficulty with the second argument that's declared in the forEach function call. Clearly the anonymous function is passed into forEach via the action argument, but how exactly does it work once inside the for loop?
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
var numbers = [1, 2, 3, 4, 5], sum = 0;
forEach(numbers, function(number) {
sum += number;
});
console.log(sum); // 15
I think what confuses me most is that the syntax of the anonymous function doesn't seem compatible with action(array[i]) - I mean, I understand that sum acquires each value of the array in turn, but if the function "replaces" the action argument, how and where does the (array[i]) part fit in?
Let me rewrite that code in a more explicit way:
function forEach(array, action) { //1st parameter is an array, the 2nd is a function
for (var i = 0; i < array.length; i++)
action(array[i]); //The function is used, with each element of the array as parameter
}
var numbers = [1, 2, 3, 4, 5], sum = 0;
var myFunction= function (number) { //I declare a function which receives a number
sum += number; //and adds it to sum.
}
forEach(numbers,myFunction); //I call the forEach function using the
// variables I previously created as parameters
console.log(sum);
In javascript when you define a variable you write:
var x = 0; // here you reserve an object
And when you define a function also you reserve an object. Javascript deal with functions as objects and you can assign it to any variable:
var x = function(number){ sum +=number; };
forEach (numbers, x(number) );
And about the confused syntax, Anonymous functions are functions that are dynamically declared at runtime. They’re called anonymous functions because they aren’t given a name in the same way as normal functions.
So to call an Anonymous function you follow this syntax:
// call
function (param1, param2, ...){
// function body
}
if you want to call it again either you should repeat the code above or declare a function without calling it and save it on variable where you can call it many times:
// declaration
var x = function(param1, param2, ...){
// body
};
// call
x(p1,p2,....);

JavaScript: Partial Function, why is necessary to do with Array.prototype.slice.call(arguments)

I wanted to do a partial_left function that will be executed into an array, something liek that:
array_1.map(partial_left1(equal));
function equal(x){return x;}
, but I crushed when I pushed the variables of arguments into an other array(and not with the Array.prototype.slice.call(arguments)). Because I wanna do other way, But I surprised when the result were differents:
var array_1=[1,2,3];
with my method: th result is : [1,1,1]//doing reference only to the array[0]
with Array,prototype.slice.call: [1,2,3]//how I would want to be
this is my code, where I push the values of arguments in another array:
function concat(arg1,arg2,n){
for (var i = n; i < arg2.length; i++)
arg1.push(arg2[i]);
return arg1;
}
function partial_left1(f){
var argum_apply=[];
argum_apply=concat(argum_apply,arguments,1);
return function(){
argum_apply=concat(argum_apply,arguments,0);
return f.apply(this,argum_apply);
};
}
And this is the code with Array.prototype.slice.call:
function array(a, n) { return Array.prototype.slice.call(a, n || 0); }
function partial_left2(f /*, ...*/) {
var args = arguments;
return function() {
var a = array(args, 1);
a = a.concat(array(arguments));
return f.apply(this, a);
};
}
A simple definition of equal with partial:
var equal_left1=partial_left1(equal);
var equal_left2=partial_left2(equal);
Here are the results, and I don't know why they are differents?
var array_1=[1,2,3];
alert(array_1.map(equal_left1));//1,1,1
alert(array_1.map(equal_left2));//1,2,3
Someones who knows please explain me what are the differences between "Concat" and use "Array.prototype.slice.call"?
One of the bad design decisions: arguments is not an array. It is array-like, in the sense it has a length property.
You can't call the concat method of arguments because it doesn't exist.
Array.prototype.slice.call uses the slice method from the arrays and invokes it -- it is a quick and easy way to turn something array-like to a proper array.
You can do the same thing with a loop, if you want:
var arr = [];
for (var i = 0; i < arguments.length; i++) {
arr[i] = arguments[i];
}

how to create functions with variable arguments in javascript?

I want to create a function in javascript with a variable amount of arguments. The next example is how I want to call this function:
myFunction(1,2);
myFunction(1,2,3);
myFunction(1,2,3,4);
myFunction(1,2,3,4,5);
myFunction(1,2,3,4,5,6);
Anyone knows how to define this function?
You can access the arguments by their ordinal position without the need to state them in the prototype as follows:
function myFunction() {
for (var i = 0; i < arguments.length; i++)
alert(arguments[i]);
}
myFunction(1, 2, "three");
>>1
>>2
>>three
Or if you really are passing in a set of semantically related numbers you could use an array;
function myFunction(arr) { ... }
result = myFunction([1,2,3]);
Latest update
Rest parameters are supported in all new browsers.
Check here for details
The rest parameter syntax allows us to represent an indefinite number of arguments as an array, which you can pass it to other functions too.
function myFunction(...data){
console.log(...data);
myOtherFunction(...data);
}
myFunction(1,2,3); //logs 1,2,3
myFunction([1,2,3]); //logs [1,2,3]
Use the 'arguments' variable like this :
function myFunction() {
alert(arguments.length + ' arguments');
for( var i = 0; i < arguments.length; i++ ) {
alert(arguments[i]);
}
}
Call the methods as you did before
myFunction(1,2);
myFunction(1,2,3,4,5,6);
Just refer to the arguments array.
https://developer.mozilla.org/en/JavaScript/Reference/functions_and_function_scope/arguments
If an argument is not present, use the default. Like this...
function accident() {
//Mandatory Arguments
var driver = arguments[0];
var condition = arguments[1]
//Optional Arguments
var blame_on = (arguments[2]) ? arguments[2] : "Irresponsible tree" ;
}
accident("Me","Drunk");
As an add-on: You can assign values to the unnamed function parameters, as in (german wiki)
arguments[0] = 5;

Categories