How can I convert the "arguments" object to an array in JavaScript? - javascript

Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
The arguments object in JavaScript is an odd wart—it acts just like an array in most situations, but it's not actually an array object. Since it's really something else entirely, it doesn't have the useful functions from Array.prototype like forEach, sort, filter, and map.
It's trivially easy to construct a new array from an arguments object with a simple for loop. For example, this function sorts its arguments:
function sortArgs() {
var args = [];
for (var i = 0; i < arguments.length; i++)
args[i] = arguments[i];
return args.sort();
}
However, this is a rather pitiful thing to have to do simply to get access to the extremely useful JavaScript array functions. Is there a built-in way to do it using the standard library?

ES6 using rest parameters
If you are able to use ES6 you can use:
Rest Parameters
function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
As you can read in the link
The rest parameter syntax allows us to represent an indefinite number of arguments as an array.
If you are curious about the ... syntax, it is called Spread Operator and you can read more here.
ES6 using Array.from()
Using Array.from:
function sortArgs() {
return Array.from(arguments).sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(12, 4, 6, 8).toString();
Array.from simply convert Array-like or Iterable objects into Array instances.
ES5
You can actually just use Array's slice function on an arguments object, and it will convert it into a standard JavaScript array. You'll just have to reference it manually through Array's prototype:
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}
Why does this work? Well, here's an excerpt from the ECMAScript 5 documentation itself:
NOTE: The slice function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be transferred to other kinds of objects for use as a method. Whether the slice function can be applied successfully to a host object is implementation-dependent.
Therefore, slice works on anything that has a length property, which arguments conveniently does.
If Array.prototype.slice is too much of a mouthful for you, you can abbreviate it slightly by using array literals:
var args = [].slice.call(arguments);
However, I tend to feel that the former version is more explicit, so I'd prefer it instead. Abusing the array literal notation feels hacky and looks strange.

It's also worth referencing this Bluebird promises library wiki page that shows how to manage the arguments object into array in a way that makes the function optimizable under V8 JavaScript engine:
function doesntLeakArguments() {
var args = new Array(arguments.length);
for(var i = 0; i < args.length; ++i) {
args[i] = arguments[i];
}
return args;
}
This method is used in favor of var args = [].slice.call(arguments);. The author also shows how a build step can help reduce the verbosity.

function sortArgs(){ return [].slice.call(arguments).sort() }
// Returns the arguments object itself
function sortArgs(){ return [].sort.call(arguments) }
Some array methods are intentionally made not to require the target object to be an actual array. They only require the target to have a property named length and indices (which must be zero or larger integers).
[].sort.call({0:1, 1:0, length:2}) // => ({0:0, 1:1, length:2})

Use:
function sortArguments() {
return arguments.length === 1 ? [arguments[0]] :
Array.apply(null, arguments).sort();
}
Array(arg1, arg2, ...) returns [arg1, arg2, ...]
Array(str1) returns [str1]
Array(num1) returns an array that has num1 elements
You must check number of arguments!
Array.slice version (slower):
function sortArguments() {
return Array.prototype.slice.call(arguments).sort();
}
Array.push version (slower, faster than slice):
function sortArguments() {
var args = [];
Array.prototype.push.apply(args, arguments);
return args.sort();
}
Move version (slower, but small size is faster):
function sortArguments() {
var args = [];
for (var i = 0; i < arguments.length; ++i)
args[i] = arguments[i];
return args.sort();
}
Array.concat version (slowest):
function sortArguments() {
return Array.prototype.concat.apply([], arguments).sort();
}

If you're using jQuery, the following is a good deal easier to remember in my opinion:
function sortArgs(){
return $.makeArray(arguments).sort();
}

In ECMAScript 6 there's no need to use ugly hacks like Array.prototype.slice(). You can instead use spread syntax (...).
(function() {
console.log([...arguments]);
}(1, 2, 3))
It may look strange, but it's fairly simple. It just extracts arguments' elements and put them back into the array. If you still don't understand, see this examples:
console.log([1, ...[2, 3], 4]);
console.log([...[1, 2, 3]]);
console.log([...[...[...[1]]]]);
Note that it doesn't work in some older browsers like IE 11, so if you want to support these browsers, you should use Babel.

Here is benchmark of several methods converting arguments into array.
As for me, the best solution for small amount of arguments is:
function sortArgs (){
var q = [];
for (var k = 0, l = arguments.length; k < l; k++){
q[k] = arguments[k];
}
return q.sort();
}
For other cases:
function sortArgs (){ return Array.apply(null, arguments).sort(); }

Here's a clean and concise solution:
function argsToArray() {
return Object.values(arguments);
}
// example usage
console.log(
argsToArray(1, 2, 3, 4, 5)
.map(arg => arg*11)
);
Object.values( ) will return the values of an object as an array, and since arguments is an object, it will essentially convert arguments into an array, thus providing you with all of an array's helper functions such as map, forEach, filter, etc.

I recommend using ECMAScript 6 spread operator, which will Bind trailing parameters to an array. With this solution you don't need to touch the arguments object and your code will be simplified. The downside of this solution is that it does not work across most browsers, so instead you will have to use a JS compiler such as Babel. Under the hood Babel transforms arguments into a Array with a for loop.
function sortArgs(...args) {
return args.sort();
}
If you can not use a ECMAScript 6, I recommend looking at some of the other answers such as #Jonathan Fingland
function sortArgs() {
var args = Array.prototype.slice.call(arguments);
return args.sort();
}

Lodash:
var args = _.toArray(arguments);
in action:
(function(){ console.log(_.toArray(arguments).splice(1)); })(1, 2, 3)
produces:
[2,3]

Use Array.from(), which takes an array-like object (such as arguments) as argument and converts it to array:
(function() {
console.log(Array.from(arguments));
}(1, 2, 3));
Note that it doesn't work in some older browsers like IE 11, so if you want to support these browsers, you should use Babel.

function sortArg(){
var args = Array.from(arguments); return args.sort();
}
function sortArg(){
var args = Array.from(arguments);
return args.sort();
}
console.log(sortArg('a', 'b', 1, 2, '34', 88, 20, '19', 39, 'd', 'z', 'ak', 'bu', 90));

Another Answer.
Use Black Magic Spells:
function sortArguments() {
arguments.__proto__ = Array.prototype;
return arguments.slice().sort();
}
Firefox, Chrome, Node.js, IE11 are OK.

Try using Object.setPrototypeOf()
Explanation: Set prototype of arguments to Array.prototype
function toArray() {
return Object.setPrototypeOf(arguments, Array.prototype)
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explanation: Take each index of arguments , place item into an array at corresponding index of array.
could alternatively use Array.prototype.map()
function toArray() {
return [].map.call(arguments, (_,k,a) => a[k])
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
Explanation: Take each index of arguments , place item into an array at corresponding index of array.
for..of loop
function toArray() {
let arr = []; for (let prop of arguments) arr.push(prop); return arr
}
console.log(toArray("abc", 123, {def:456}, [0,[7,[14]]]))
or Object.create()
Explanation: Create object, set properties of object to items at each index of arguments; set prototype of created object to Array.prototype
function toArray() {
var obj = {};
for (var prop in arguments) {
obj[prop] = {
value: arguments[prop],
writable: true,
enumerable: true,
configurable: true
}
}
return Object.create(Array.prototype, obj);
}
console.log(toArray("abc", 123, {def: 456}, [0, [7, [14]]]))

Benshmarck 3 methods :
function test()
{
console.log(arguments.length + ' Argument(s)');
var i = 0;
var loop = 1000000;
var t = Date.now();
while(i < loop)
{
Array.prototype.slice.call(arguments, 0);
i++;
}
console.log(Date.now() - t);
i = 0,
t = Date.now();
while(i < loop)
{
Array.apply(null, arguments);
i++;
}
console.log(Date.now() - t);
i = 0,
t = Date.now();
while(i < loop)
{
arguments.length == 1 ? [arguments[0]] : Array.apply(null, arguments);
i++;
}
console.log(Date.now() - t);
}
test();
test(42);
test(42, 44);
test(42, 44, 88, 64, 10, 64, 700, 15615156, 4654, 9);
test(42, 'truc', 44, '47', 454, 88, 64, '#ehuehe', 10, 64, 700, 15615156, 4654, 9,97,4,94,56,8,456,156,1,456,867,5,152489,74,5,48479,89,897,894,894,8989,489,489,4,489,488989,498498);
RESULT?
0 Argument(s)
256
329
332
1 Argument(s)
307
418
4
2 Argument(s)
375
364
367
10 Argument(s)
962
601
604
40 Argument(s)
3095
1264
1260
Enjoy !

function sortArgs(...args) {
return args.sort(function (a, b) { return a - b; });
}
document.body.innerHTML = sortArgs(1, 2, 3, 4).toString();

Although rest parameters work well, if you want to continue to use arguments for some reason, consider
function sortArgs() {
return [...arguments].sort()
}
[...arguments] can be considered a sort of alternative to Array.from(arguments), which also works perfectly well.
An ES7 alternative is an array comprehension:
[for (i of arguments) i].sort()
This could be easiest if you want to process or filter the arguments prior to sorting:
[for (i of arguments) if (i % 2) Math.log(i)].sort()

function x(){
var rest = [...arguments]; console.log(rest);return
rest.constructor;
};
x(1,2,3)
I tried simple destructing technique

The Arguments object is only available inside a function body. Although you can index the Arguments Object like an array, it is not an array. It does not have any array properties other than length.
// function arguments length 5
function properties(a,b,c,d,e){
var function_name= arguments.callee.name
var arguments_length= arguments.length;
var properties_length= properties.length;
var function_from= properties.caller.name;
console.log('I am the function name: '+ function_name);
console.log('I am the function length, I am function spacific: '+ properties_length);
console.log('I am the arguments length, I am context/excution spacific: '+ arguments_length);
console.log('I am being called From: '+ function_from );
}
// arguments 3
function parent(){
properties(1,2,3);
}
//arguments length 3 because execution spacific
parent();
Although it can be indexed like an array as you can see in this example:
function add(){
var sum=0;
for(var i=0; i< arguments.length;i++){
sum = sum + arguments[i];
}
return sum;
}
console.log(add(1,2,3));
However, the Arguments object is not an array and does not have any other properties other than length.
You can convert the arguments object into an array at which point you can access the Arguments object.
There are many ways you can access the arguments object inside a function body, and these include:
you can call the Array.prototoype.slice.call method.
Array.prototype.slice.call(arguments)
function giveMeArgs(arg1,arg2){
var args = Array.prototype.slice.call(arguments);
return args
}
console.log( giveMeArgs(1,2));
you can use the array literal
[].slice.call(arguments).
function giveMeArgs(arg1,arg2){
var args = [].slice.call(arguments);
return args;
}
console.log( giveMeArgs(1,2) );
you can use Rest ...
function giveMeArgs(...args){
return args;
}
console.log(giveMeArgs(1,2))
you can use spread [...]
function giveMeArgs(){
var args = [...arguments];
return args;
}
console.log(giveMeArgs(1,2));
you can use Array.from()
function giveMeArgs(){
var args = Array.from(arguments);
return args;
}
console.log(giveMeArgs(1,2));

You can create a reusable function to do it with any arguments, the simplest one is something like this:
function sortArgs() {
return [...arguments].sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
Spread syntax can be used in ES6 and above...
But if you'd like to use something compatible with ES5 and below, you can use Array.prototype.slice.call, so you code looks like this:
function sortArgs() {
return Array.prototype.slice.call(arguments).sort();
}
sortArgs('ali', 'reza', 1, 2, 'a'); //[1, 2, "a", "ali", "reza"];
There are also few other ways to do this, for Example using Array.from or loop through the arguments and assign them to a new array...

This is a very old question, but I think I have a solution that is slightly easier to type than previous solutions and doesn't rely on external libraries:
function sortArguments() {
return Array.apply(null, arguments).sort();
}

Related

May someone help me why my console returns only 0 when i input this data in console? [duplicate]

In PHP there is func_num_args and func_get_args, is there something similar for JavaScript?
For modern Javascript or Typescript:
class Foo {
reallyCoolMethodISwear(...args) { return args.length; }
}
function reallyCoolFunction(i, ...args) { return args[i]; }
const allHailTheLambda = (...args) => {
return args.constructor == Array;
};
const x = new Foo().reallyCoolMethodISwear(0, 1, 2, 3, 4);
const y = reallyCoolFunction(3, 0, 1, 2, 3, 4, 5, 6);
const z = allHailTheLambda(43110, "world");
console.log(x, y, z); // 5 3 true
For ancient Javascript:
Use arguments. You can access it like an array. Use arguments.length for the number of arguments.
The arguments is an array-like object (not an actual array). Example function...
function testArguments () // <-- notice no arguments specified
{
console.log(arguments); // outputs the arguments to the console
var htmlOutput = "";
for (var i=0; i < arguments.length; i++) {
htmlOutput += '<li>' + arguments[i] + '</li>';
}
document.write('<ul>' + htmlOutput + '</ul>');
}
Try it out...
testArguments("This", "is", "a", "test"); // outputs ["This","is","a","test"]
testArguments(1,2,3,4,5,6,7,8,9); // outputs [1,2,3,4,5,6,7,8,9]
The full details: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments
ES6 allows a construct where a function argument is specified with a "..." notation such as
function testArgs (...args) {
// Where you can test picking the first element
console.log(args[0]);
}
The arguments object is where the functions arguments are stored.
The arguments object acts and looks like an array, it basically is, it just doesn't have the methods that arrays do, for example:
Array.forEach(callback[, thisArg]);
Array.map(callback[, thisArg])
Array.filter(callback[, thisArg]);
Array.slice(begin[, end])
Array.indexOf(searchElement[, fromIndex])
I think the best way to convert a arguments object to a real Array is like so:
argumentsArray = [].slice.apply(arguments);
That will make it an array;
reusable:
function ArgumentsToArray(args) {
return [].slice.apply(args);
}
(function() {
args = ArgumentsToArray(arguments);
args.forEach(function(value) {
console.log('value ===', value);
});
})('name', 1, {}, 'two', 3)
result:
> value === name
> value === 1
> value === Object {}
> value === two
> value === 3
You can also convert it to an array if you prefer. If Array generics are available:
var args = Array.slice(arguments)
Otherwise:
var args = Array.prototype.slice.call(arguments);
from Mozilla MDN:
You should not slice on arguments because it prevents optimizations in
JavaScript engines (V8 for example).
As many other pointed out, arguments contains all the arguments passed to a function.
If you want to call another function with the same args, use apply
Example:
var is_debug = true;
var debug = function() {
if (is_debug) {
console.log.apply(console, arguments);
}
}
debug("message", "another argument")
Similar answer to Gunnar, with more complete example:
You can even transparently return the whole thing:
function dumpArguments(...args) {
for (var i = 0; i < args.length; i++)
console.log(args[i]);
return args;
}
dumpArguments("foo", "bar", true, 42, ["yes", "no"], { 'banana': true });
Output:
foo
bar
true
42
["yes","no"]
{"banana":true}
https://codepen.io/fnocke/pen/mmoxOr?editors=0010
Yes if you have no idea that how many arguments are possible at the time of function declaration then you can declare the function with no parameters and can access all variables by arguments array which are passed at the time of function calling.
In ES6 you can do something like this:
function foo(...args)
{
let [a,b,...c] = args;
console.log(a,b,c);
}
foo(1, null,"x",true, undefined);
Hope this helps:
function x(...args) {
console.log( {...[...args] } );
}
x({a:1,b:2}, 'test');
Output:
{ '0': { a: 1, b: 2 }, '1': 'test' }
Hope this could be the helpful code:
function lazyLoadIcons(){
for(let i = 0; i < arguments.length; i++) {
var elements = document.querySelectorAll(arguments[i]);
elements.forEach(function(item){
item.classList.add('loaded');
});
}
}
lazyLoadIcons('.simple-2col', '.ftr-blue-ad', '.btm-numb');
~ Rahul Daksh
In ES6, use Array.from:
function foo()
{
foo.bar = Array.from(arguments);
foo.baz = foo.bar.join();
}
foo(1,2,3,4,5,6,7);
foo.bar // Array [1, 2, 3, 4, 5, 6, 7]
foo.baz // "1,2,3,4,5,6,7"
For non-ES6 code, use JSON.stringify and JSON.parse:
function foo()
{
foo.bar = JSON.stringify(arguments);
foo.baz = JSON.parse(foo.bar);
}
/* Atomic Data */
foo(1,2,3,4,5,6,7);
foo.bar // "{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7}"
foo.baz // [object Object]
/* Structured Data */
foo({1:2},[3,4],/5,6/,Date())
foo.bar //"{"0":{"1":2},"1":[3,4],"2":{},"3":"Tue Dec 17 2013 16:25:44 GMT-0800 (Pacific Standard Time)"}"
foo.baz // [object Object]
If preservation is needed instead of stringification, use the internal structured cloning algorithm.
If DOM nodes are passed, use XMLSerializer as in an unrelated question.
with (new XMLSerializer()) {serializeToString(document.documentElement) }
If running as a bookmarklet, you may need to wrap the each structured data argument in an Error constructor for JSON.stringify to work properly.
References
Structure Clone CommonJS Module
JS Object Clone
MDN: Array.from()

Array spread alternative for Internet Explorer [duplicate]

I'd like to call a function using an array as parameters:
const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it
function call_me (param0, param1, param2 ) {
// ...
}
Is there a better way of passing the contents of x into call_me()?
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);
See MDN docs for Function.prototype.apply().
If the environment supports ECMAScript 6, you can use a spread argument instead:
call_me(...args);
Why don't you pass the entire array and process it as needed inside the function?
var x = [ 'p0', 'p1', 'p2' ];
call_me(x);
function call_me(params) {
for (i=0; i<params.length; i++) {
alert(params[i])
}
}
In ES6 standard there is a new spread operator ... which does exactly that.
call_me(...x)
It is supported by all major browsers except for IE.
The spread operator can do many other useful things, and the linked documentation does a really good job at showing that.
Assuming that call_me is a global function, so you don't expect this to be set.
var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
As #KaptajnKold had answered
var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);
And you don't need to define every parameters for call_me function either.
You can just use arguments
function call_me () {
// arguments is a array consisting of params.
// arguments[0] == 'p0',
// arguments[1] == 'p1',
// arguments[2] == 'p2'
}
While using spread operator we must note that it must be the last or only parameter passed. Else it will fail.
function callMe(...arr){ //valid arguments
alert(arr);
}
function callMe(name, ...arr){ //valid arguments
alert(arr);
}
function callMe(...arr, name){ //invalid arguments
alert(arr);
}
If you need to pass an array as the starting argument you can do:
function callMe(arr, name){
let newArr = [...arr];
alert(newArr);
}
Function arguments may also be Arrays:
function foo([a,b,c], d){
console.log(a,b,c,d);
}
foo([1,2,3], 4)
of-course one can also use spread:
function foo(a, b, c, d){
console.log(a, b, c, d);
}
foo(...[1, 2, 3], 4)
Note this
function FollowMouse() {
for(var i=0; i< arguments.length; i++) {
arguments[i].style.top = event.clientY+"px";
arguments[i].style.left = event.clientX+"px";
}
};
//---------------------------
html page
<body onmousemove="FollowMouse(d1,d2,d3)">
<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>
</body>
can call function with any Args
<body onmousemove="FollowMouse(d1,d2)">
or
<body onmousemove="FollowMouse(d1)">
you can use the spread syntax
for example:
function print(...inpu){
console.log(...inpu)
}
var arry = ['p0','p1','p2']
print(...arry)
here is the link: modzilla spread syntax refrence document
you can use spread operator in a more basic form
[].concat(...array)
in the case of functions that return arrays but are expected to pass as arguments
Example:
function expectArguments(...args){
return [].concat(...args);
}
JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))
The answer was already given, but I just want to give my piece of cake. What you want to achieve is called method borrowing in the context of JS, that when we take a method from an object and call it in the context of another object. It is quite common to take array methods and apply them to arguments. Let me give you an example.
So we have "super" hashing function which takes two numbers as an argument and returns "super safe" hashed string:
function hash() {
return arguments[0]+','+arguments[1];
}
hash(1,2); // "1,2" whoaa
So far so good, but we have little problem with the above approach, it is constrained, only works with two numbers, that is not dynamic, let's make it work with any number and plus you do not have to pass an array (you can if you still insist). Ok, Enough talk, Let's fight!
The natural solution would be to use arr.join method:
function hash() {
return arguments.join();
}
hash(1,2,4,..); // Error: arguments.join is not a function
Oh, man. Unfortunately, that won’t work. Because we are calling hash(arguments) and arguments object is both iterable and array-like, but not a real array. How about the below approach?
function hash() {
return [].join.call(arguments);
}
hash(1,2,3,4); // "1,2,3,4" whoaa
The trick is called method borrowing.
We borrow a join method from a regular array [].join. And use [].join.call to run it in the context of arguments.
Why does it work?
That’s because the internal algorithm of the native method arr.join(glue) is very simple.
Taken from the specification almost “as-is”:
Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
…Do so until this.length items are glued.
Return result.
So, technically it takes this and joins this[0], this[1] …etc together. It’s intentionally written in a way that allows any array-like this (not a coincidence, many methods follow this practice). That’s why it also works with this=arguments.
There's a better way using JSON not an Array!
// Call a function with a Json Key / Value Pair:
sendMail({param1: p1, param2: p2});
// Function definition and usage of value pairs:
function sendMail(data){
var parameter1 = data.param1;
var parameter2 = data.param2;
}

How to extend built-in objects in Javascript, For example Math?

Was learning Call, Apply, Bind trio.
Then tried this:
Math.__proto__.sum = function(arg1){var res=0; for(i in arg1) res+=arg1[i]; return res; };
Math.sum([1,2,3])
//Output: "6function (arg1){var res=0; for(i in arg1) res+=arg1[i]; return res; }"
Why does this output contains function defination attached with the sum output?
How do we extend a built-in object like Math in a project with such utility methods and use it all over?
Thanks :)
This is a classic example of why you don't mess with __proto__ (unless you absolutely know what you're doing). Attaching a function to Object.prototype as an enumerable property causes it to be iterated in your for...in loop since Array extends Object. This results in the function being concatenated to your sum and coerced to a string.
If you want to add functionality to Math, for most purposes, you can just assign directly to Math:
Math.sum = function() {...}
JavaScript allows you to modify native objects:
Math.sayHello = function(friend) {
alert('Hello there ' + friend);
}
Math.sayHello('buddy');
Of course this could soon be messy when you actually redefine methods.
Math.ceil = function(x) {
return parseInt(x, 10);
}
console.log(Math.ceil(4.9));
It is better to implement a method for Math in the same manner as Math.max which take the arguments and returns a folded result.
Math.add = (...args) => args.reduce((a, b) => a + b, 0);
console.log(Math.add(1, 2, 3));
console.log(Math.add(...[7, 8, 9]));
Only ES5
Math.add = function () {
var i = arguments.length,
sum = 0;
while (i--) {
sum += arguments[i];
}
return sum;
};
console.log(Math.add(1, 2, 3));
console.log(Math.add.apply(null, [7, 8, 9]));

Javascript, looping through an array and the arguments "object"

I can't get my head around this, i'm using filter to loop through an array and filter out all the integers passed as arguments ,i'm not limited in the number of arguments.
But i'm stuck here when it's about to get back to the function the value of the arguments object, at least more that once.
In my code below, obviously it's not fully working because i'm doing a return within the for…in loop, this is where i don't get how I can get the this second loop without having i re-initialised to 0…
function destroyer(arr) {
var args = arguments.length;
var arg0 = arguments[0];
var Nargs = Array.prototype.slice.call(arguments, 1);
var newArr = [];
newArr = arg0.filter(filtre);
/*Only the first argument is
filtered out,here it's the value "2",
but should filter out [2,3].
The expected result is [1,1]*/
console.log(newArr);
return newArr;
function filtre(e){
for (var i in Nargs){
return e !== Nargs[i];
}
}
}
destroyer([1, 2, 3, 1, 2, 3], 2,3);
Hope this is clear enough,
Thanks for any input !
Matth.
While rgthree provided a solution very similar to what you already had, I wanted to provide a solution that takes advantage of newer ES6 features for modern browsers. If you run this through Babel, it will result in essentially the same code as in that solution, though it will still require a shim for the includes call.
function destroyer(source, ...args) {
return source.filter(el => !args.includes(el));
}
Explanation:
...args uses the spread operator to get all but the first argument into an array named args.
We can directly return the filtered array, assuming you don't need to log it and that was just for debugging.
el => !args.includes(el) is an anonymous arrow function. Since no braces are used, it will automatically return the result of the expression.
Since args is an array, we can directly use Array.prototype.includes to check if the current element is in the arguments to be removed. If it exists, we want to remove it and thus invert the return with !. An alternative could be the following: el => args.includes(el) == false.
Since your return statement in your filtre function is always executed on the first run, it's only returning the whether the first number in Nargs is equal to the current item. Instead, you can use indexOf for full browser support (which returns the index of the item in an array, or "-1" if it's not in an array) instead of a loop (or includes, or a loop, etc. as shown further below):
function destroyer(arr) {
var args = arguments.length;
var arg0 = arguments[0];
var Nargs = Array.prototype.slice.call(arguments, 1);
var newArr = [];
function filtre(e){
return Nargs.indexOf(e) === -1;
}
newArr = arg0.filter(filtre);
console.log(newArr);
return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2,3);
If you don't need Internet Explorer support, you could use Array.includes:
function filtre(e){
return !Nargs.includes(e);
}
And finally, if you really wanted to use a loop, you would only want to filter an item (return false) once it's found otherwise allow it (return true):
function filtre(e){
for (var i = 0, l = Nargs.length; i < l; i++) {
if (e === Nargs[i])
return false;
}
return true;
}

Passing an array as a function parameter in JavaScript

I'd like to call a function using an array as parameters:
const x = ['p0', 'p1', 'p2'];
call_me(x[0], x[1], x[2]); // I don't like it
function call_me (param0, param1, param2 ) {
// ...
}
Is there a better way of passing the contents of x into call_me()?
const args = ['p0', 'p1', 'p2'];
call_me.apply(this, args);
See MDN docs for Function.prototype.apply().
If the environment supports ECMAScript 6, you can use a spread argument instead:
call_me(...args);
Why don't you pass the entire array and process it as needed inside the function?
var x = [ 'p0', 'p1', 'p2' ];
call_me(x);
function call_me(params) {
for (i=0; i<params.length; i++) {
alert(params[i])
}
}
In ES6 standard there is a new spread operator ... which does exactly that.
call_me(...x)
It is supported by all major browsers except for IE.
The spread operator can do many other useful things, and the linked documentation does a really good job at showing that.
Assuming that call_me is a global function, so you don't expect this to be set.
var x = ['p0', 'p1', 'p2'];
call_me.apply(null, x);
As #KaptajnKold had answered
var x = [ 'p0', 'p1', 'p2' ];
call_me.apply(this, x);
And you don't need to define every parameters for call_me function either.
You can just use arguments
function call_me () {
// arguments is a array consisting of params.
// arguments[0] == 'p0',
// arguments[1] == 'p1',
// arguments[2] == 'p2'
}
While using spread operator we must note that it must be the last or only parameter passed. Else it will fail.
function callMe(...arr){ //valid arguments
alert(arr);
}
function callMe(name, ...arr){ //valid arguments
alert(arr);
}
function callMe(...arr, name){ //invalid arguments
alert(arr);
}
If you need to pass an array as the starting argument you can do:
function callMe(arr, name){
let newArr = [...arr];
alert(newArr);
}
Function arguments may also be Arrays:
function foo([a,b,c], d){
console.log(a,b,c,d);
}
foo([1,2,3], 4)
of-course one can also use spread:
function foo(a, b, c, d){
console.log(a, b, c, d);
}
foo(...[1, 2, 3], 4)
Note this
function FollowMouse() {
for(var i=0; i< arguments.length; i++) {
arguments[i].style.top = event.clientY+"px";
arguments[i].style.left = event.clientX+"px";
}
};
//---------------------------
html page
<body onmousemove="FollowMouse(d1,d2,d3)">
<p><div id="d1" style="position: absolute;">Follow1</div></p>
<div id="d2" style="position: absolute;"><p>Follow2</p></div>
<div id="d3" style="position: absolute;"><p>Follow3</p></div>
</body>
can call function with any Args
<body onmousemove="FollowMouse(d1,d2)">
or
<body onmousemove="FollowMouse(d1)">
you can use the spread syntax
for example:
function print(...inpu){
console.log(...inpu)
}
var arry = ['p0','p1','p2']
print(...arry)
here is the link: modzilla spread syntax refrence document
you can use spread operator in a more basic form
[].concat(...array)
in the case of functions that return arrays but are expected to pass as arguments
Example:
function expectArguments(...args){
return [].concat(...args);
}
JSON.stringify(expectArguments(1,2,3)) === JSON.stringify(expectArguments([1,2,3]))
The answer was already given, but I just want to give my piece of cake. What you want to achieve is called method borrowing in the context of JS, that when we take a method from an object and call it in the context of another object. It is quite common to take array methods and apply them to arguments. Let me give you an example.
So we have "super" hashing function which takes two numbers as an argument and returns "super safe" hashed string:
function hash() {
return arguments[0]+','+arguments[1];
}
hash(1,2); // "1,2" whoaa
So far so good, but we have little problem with the above approach, it is constrained, only works with two numbers, that is not dynamic, let's make it work with any number and plus you do not have to pass an array (you can if you still insist). Ok, Enough talk, Let's fight!
The natural solution would be to use arr.join method:
function hash() {
return arguments.join();
}
hash(1,2,4,..); // Error: arguments.join is not a function
Oh, man. Unfortunately, that won’t work. Because we are calling hash(arguments) and arguments object is both iterable and array-like, but not a real array. How about the below approach?
function hash() {
return [].join.call(arguments);
}
hash(1,2,3,4); // "1,2,3,4" whoaa
The trick is called method borrowing.
We borrow a join method from a regular array [].join. And use [].join.call to run it in the context of arguments.
Why does it work?
That’s because the internal algorithm of the native method arr.join(glue) is very simple.
Taken from the specification almost “as-is”:
Let glue be the first argument or, if no arguments, then a comma ",".
Let result be an empty string.
Append this[0] to result.
Append glue and this[1].
Append glue and this[2].
…Do so until this.length items are glued.
Return result.
So, technically it takes this and joins this[0], this[1] …etc together. It’s intentionally written in a way that allows any array-like this (not a coincidence, many methods follow this practice). That’s why it also works with this=arguments.
There's a better way using JSON not an Array!
// Call a function with a Json Key / Value Pair:
sendMail({param1: p1, param2: p2});
// Function definition and usage of value pairs:
function sendMail(data){
var parameter1 = data.param1;
var parameter2 = data.param2;
}

Categories

Resources