How String.concat() implements in javascript? - javascript

In function .concat(), I can pass an arbitrary number of arguments to it.
I understand function overloading in C++, but I don't know how implement a function with unknown number of arguments in JavaScript.
How do I implement an arbitrary number of arguments to a function?

In javascript, you would use the built in parameter called "arguments" which is an array of all the arguments passed to the function. You can obtain it's length with arguments.length and each value from the array arguments[0], arguments[1], etc... Every function has this built in variable that you can use.
For example, a function to concatenate all strings passed to it.
function concatAll() {
var str;
for (var i = 0 ; i < arguments.length; i++) {
str += arguments[i];
}
return(str);
}
var f = concatAll("abc", "def", "ghi"); // "abcdefghi"

You can do this using the arguments object. See the examples and documentation here: https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments

Like this -
function f()
{
var i;
for(i=0; i<arguments.length; i++)
{
alert( (i+1) + "th argument: " + arguments[i]);
}
}
All the functions in javascript has a built-in parameter called arguments which is an array containing all the function arguments passed to the function. Just iterate over this array and you will be able to access all the arguments of a function.
As an example, once I've written a function which is used to enable/disable certain button if some specific fields were not empty. I wrote this function this way -
function toggleButton() // I used jquery inside this function
{
var i;
var last = arguments.length-1;
for(i=0; i<last; i++)
{
if( $.trim($(arguments[i]).val()) === "" )
return false;
}
$(arguments[last]).toggle();
return true;
}
and called this function like this -
toggleButton("#idOfFirstField", "#idOfSecondField", "#idOfButtonToToggle");
or like this -
toggleButton("#idOfFirstField", "#idOfSecondField", "#idOfThirdField", "#idOfButtonToToggle");
so in both the cases, I was passing variable number of field ids to the function and it checked that if these fields were empty. If all of them contained some value, then it toggled the visibility of the button.

Like this - use the arguments object all functions have available :
function someFunction() {
for (var i=0,n=arguments.length;i<n;i++) {
// do something with arguments[i];
}
}

You can use the arguments array to access parameters that are not formally declared inside the function:
function printArguments() {
for (i = 0; i < printArguments.arguments.length; i++)
document.writeln(printArguments.arguments[i] + '<br />');
}
printArguments(1, 2, 3, 'etc');
Source: http://www.irt.org/articles/js008/

Any javascript function can have an arbitrary number of arguments. If function execution depends on the number or specific qualities of it's arguments, you'll have to check the arguments object, which can be iterated like an 'Arraylike' object, as others have shown.
In some cases it may be handy to convert the arguments to a real array, using something like
var args = Array.prototoype.slice(arguments).
Here's a blog entry from John Resigs page on method overloading that may interest you.

Related

How to use apply with currying?

I have code that is using currying to get the average on an array that results from concatenating two arrays: an n size array and an m size array.
var avg = function(...n){
let tot=0;
for(let i=0; i<n.length; i++){
tot += n[i];
}
return tot/n.length;
};
var spiceUp = function(fn, ...n){
return function(...m){
return fn.apply(this, n.concat(m));
}
};
var doAvg = spiceUp(avg, 1,2,3);
console.log(doAvg(4,5,6));
In this line return fn.apply(this, n.concat(m));, I don't understand why do we need to use apply. What is the object we are binding with the average function and why does just normal calling (return fn(n.concat(m));) not work?
In that example, this is not that important. It would also work if instead of this you would pass an empty object instead. It's just an example on how to use apply.
What you need to focus is on the second parameter n.concat(m). They key concept here is that passing an array as a second argument you are calling that function (fn) passing each value in the array as an argument.
About your second question: no, it won't work because fn expects several arguments (one per value to calculate the average) while by doing return fn(n.concat(m)); you are just passing one argument, an array containing all values
Maybe you would understand it better with a simpler example:
function sum3params(a,b,c){
return a+b+c;
}
console.log(sum3params([3,4,2])) // won't work
console.log(sum3params.apply(this, [3,4,2])) // will work ('this' is not important here)
For this use case, it does not. But consider the following:
var foo = {
bar: 3
};
var addBar = function(a, b) { return a + b + this.bar };
foo.add3AndBar = spiceUp(addBar, 3);
foo.add3AndBar(1); // 7
Using apply means that your spiceUp function can be applied to methods as well as normal functions. For more likely example, consider partially applying when defining a method on a prototype:
const ENV = "linux";
DoesSomePlatformSpecificStuff.prototype.getPath = spiceUp(ENV);
apply also will spread the gathered array of arguments back out into positional arguments which can also be done like so:
return fn(...n.concat(m));
Which can be simplified as
return fn(...n, ...m);
Which is equivalent to
return fn.apply(undefined, n.concat(m));

Explanation of Following Javascript Code

I am fairly new to js and I have been looking at the Mozilla Developer site. Under the functions section, I can't seem to grasp the following
function map(f,a) {
var result = [], // Create a new Array
i;
for (i = 0; i != a.length; i++)
result[i] = f(a[i]);
return result;
}
particulary, this line "result[i] = f(a[i]);"
From Mozilla:
Function expressions are convenient when passing a function as an argument to another function. The following example shows a map function being defined and then called with an anonymous function as its first parameter
Can you help explain this?
Here is a link for reference.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
this piece of code applies to every element of array "a" function "f" and returns the array "result" which contains the results of running function "f" for every element in "a".
Sorry, I've got a recursion :)
Actually it can be used like that:
var array = map(function(val){ return val + 1; },[1,2,3,4,5]);
and in "array" you will have these values:
[2,3,4,5,6]
result[i] = f(a[i]);
result is an array and the element at index i is being assigned the result of a function call which takes the parameter a[i].
f in the line above is an anonymous function which is parsed into the map function as the first argument. f would be defined somewhere else in code with the following syntax
function(value) {
return result.
}
The calling code of your example above would look something like.
var array = map(function(value) { return result; },[1,2,3,4,5]);
I would read up on anonymous functions here which might help.
http://en.wikibooks.org/wiki/JavaScript/Anonymous_Functions

Creating an array with copy of object (Javascript)

I'm trying to write a "universal" array filler that fills an array with a given object. I simulted a class in javascript and now I want to write a function that fills the array with types of that class
function fillArray(theArrayToFill,amount,theObject) {
for ( var i = 0; i != amount; ++i )
{theArrayToFill.push(theObject);}
}
But fillArray (theArray,3,new Enemy(0,0)); fills the array with a reference to that object "enemy" and that's not what I want, I want an exact copy, but when I mutate object 0, object 2 may not change.
Please Help
Thanks
I would recommend you to add a clone method to your object. The clone method should create a new object and set it's value by copying the current object, then the method return this new object.
example:
function clone(obj)
{
var newObj = new YourObject();
newObj.setName(obj.getName());
//Do this for every properties
return newObj;
}
If you are using Underscore, it provides a clone helper function.
function fillArray(theArrayToFill,amount,theObject) {
for ( var i = 0; i != amount; ++i )
{theArrayToFill.push(_.clone(theObject));}
}
Since you already have the constructor, here is how you can use it:
function fillArray(theArrayToFill,amount,ctor) {
for ( var i = 0; i != amount; ++i ) {
theArrayToFill.push(new ctor(0,0));
}
}
// usage:
fillArray(theArray,3,Enemy);
The way you originally called the fillArray method, you created one object (immediately before the function is called) and passed it as parameter to the fillArray method. The method then proceded to fill the array with references towards that object, so each item in the array would indeed point towards the same object.
EDIT:
No simple solution comes to mind if you want to pass different arguments to the constructor. Here is a hacky one that might be enough for your purposes:
function fillArray(theArrayToFill,amount,ctor) {
for ( var i = 0; i != amount; ++i ) {
theArrayToFill.push(new ctor(arguments[3], arguments[4], arguments[5],
arguments[6], arguments[7], arguments[8], arguments[9], arguments[10],
arguments[11], arguments[12], arguments[13], arguments[14]));
}
}
// usage:
fillArray(theArray,3,Enemy,0,0);
fillArray(theArray,3,Friend,1,2,3,4,5,6,7,8);
Obviously this only works for constructors with less than 12 arguments and some checks based on used parameters in a constructor will also fail, but it gets the job done.
PS: I don't suggest you use this approach. Looks like a clone method is more suited to your purpose.
you can use Object.create()
function fillArray(theArrayToFill,amount,theObject) {
for ( var i = 0; i != amount; ++i ) {
theArrayToFill.push(Object.create(theObject));
}
}
or if you want return new array filled default value you can use next code
function fillArray(amount,theObject) {
return Array.apply(null,Array(amount)).map(function(_){return Object.create(theObject);});
}

Passing Variable Number of arguments in javascript function argument-list

Can I pass a variable number of arguments into a Javascript function? I have little knowledge in JS. I want to implement something like the following:
function CalculateAB3(data, val1, val2, ...)
{
...
}
You can pass multiple parameters in your function and access them via arguments variable. Here is an example of function which returns the sum of all parameters you passed in it
var sum = function () {
var res = 0;
for (var i = 0; i < arguments.length; i++) {
res += parseInt(arguments[i]);
}
return res;
}
You can call it as follows:
sum(1, 2, 3); // returns 6
Simple answer to your question, surely you can
But personally I would like to pass a object rather than n numbers of parameters
Example:
function CalculateAB3(obj)
{
var var1= obj.var1 || 0; //if obj.var1 is null, 0 will be set to var1
//rest of parameters
}
Here || is logical operator for more info visit http://codepb.com/null-coalescing-operator-in-javascript/
A Is there a "null coalescing" operator in JavaScript? is a good read
Yes, you can make it. Use variable arguments like there:
function test() {
for(var i=0; i<arguments.length; i++) {
console.log(arguments[i])
}
}

Is there a JavaScript equivalent for C# 'params'?

I need a method that can have an arbitrary number of parameters. In C# we have the params statement. Do we have anything similar in JavaScript?
There is the arguments collection, which contains all arguments passed to the function.
There is a) no need to specify "optional" arguments in the function signature and b) any function accepts any number of parameters.
function foo() {
console.log(arguments);
}
foo(1,2,3,4); // logs [1, 2, 3, 4]
Likewise, there is no need to supply "required" arguments in a function call:
function foo(a, b, c, d) {
console.log(arguments);
}
foo(1,2); // logs [1, 2]
Any argument named in the signature but not supplied in the function call will be undefined.
Note that arguments behaves like an Array, but technically it isn't one. For example, you can call arguments[0], but you can't call arguments.slice(). What you can do to get around this is using the Array prototype:
Array.prototype.slice.call(arguments, 1, 2);
The so-called rest parameter ... is a new (ES6+) addition to the language and makes working with variadic functions more comfortable. #ArunCM's answer explains it.
I know this thread is too old but I believe something is missing here.
There is Rest parameter (introduced in ECMAScript 6) which will allow us to represent an indefinite number of arguments as an array.
It always returns an array. Which means even in defensive JavaScript land, it’s ok to do things like check .length of rest without guards.
Syntax :
function(a, b, ...theArgs) {
// ...
}
There are three main differences between rest parameters and the arguments object:
rest parameters are only the ones that haven't been given a separate name, while the arguments object contains all arguments passed to the function
the arguments object is not a real array, while rest parameters are Array instances, meaning methods like sort, map, forEach or pop can be applied on it directly;
the arguments object has additional functionality specific to itself (like the callee property).
Additional reading : Spread
function f(x, ...y) {
// y is an Array
return x * y.length;
}
console.log("Expected result : 3*2 = 6 & Actual result : " + f(3, "hello", true));
console.log("Expected result : 3*4 = 12 & Actual result : " + f(3, "a", true, "b", 1));
//here we are not passing anything to "y" but its still safe to check .length of "y" because it always return an array.
console.log("Expected result : 3*0 = 0 & Actual result : " + f(3));
Yes. arguments.
function concatStrings () {
var str = '';
for (var i = 0; i < arguments.length; i++) {
str += arguments[i];
}
return str;
}
Be aware that arguments isn't an array, so it doesn't have methods like join or push. It's just an array-like object (with numerical properties and a length property) so it can be iterated through.
JavaScript has arguments object inside functions. It contains of all params passed to the function.
More info
It is some sort of implicit in the special variable "arguments". Use like this:
function something(arg1, arg2) {
for (var i = 0; i < arguments.length; i++) {
var x = arguments[i];
}
}
Then you can call it like something(1, 2, 3, 'a', 'b', 'c')
More examples here: http://www.jtricks.com/javascript_tutorials/varargs.html
Javascript functions can accept any number of parameters by default. You can see them with the arguments variable.
See here.

Categories

Resources