Why can't I call an array method on a function's arguments?
Asked Answered
E

8

24

I have a function that can accept any number of arguments...

const getSearchFields = () => {        
    const joined = arguments.join('/'); 
};

I want a string of all the arguments being passed to the function joined with the / character. I keep getting this error:

args.join is not a function

Can someone please tell me what I'm doing wrong?

Engrave answered 15/9, 2009 at 1:41 Comment(6)
Why edit it to use ES6 syntax?Chestonchest
@TimDown Felt right when I was updating it. I guess there's valid arguments against doing it, if that''s what you're hinting at.Engrave
I dunno really, just seems a bit odd when the answers from 2009 are in ES3. I'm not on here enough now to know whether it's considered good or bad to revise old questions to modern syntax.Chestonchest
@TimDown AFAIK, it's encouraged to keep answers always up-to-date, even if the question goes stale. In this case, now the question looks less dated.Engrave
@alex, I have also updated my answer to provide an ES6 way to do it. Thanks.Dena
@CMS Wow, you're back :)Engrave
P
48

arguments is a pseudo-array, not a real one. The join method is available for arrays.

You'll need to cheat:

var convertedArray = [];

for(var i = 0; i < arguments.length; ++i)
{
 convertedArray.push(arguments[i]);
}

var argsString = convertedArray.join('/');

Similar to other posts, you can do the following as shorthand:

var argsString = Array.prototype.join.call(arguments, "/");
Picrite answered 15/9, 2009 at 1:44 Comment(3)
To convert the arguments object to an array, you could simply: var convertedArray = Array.prototype.slice.call(arguments);Dena
you could also simplify the loop by using splice.... var args = [].splice.call(arguments,0);Civil
@Russ: Shorter but will not work on IE, you should call directly the Array.prototype.slice function.Dena
E
14

As all said above, the arguments object is not really an array, but you can apply array functions directly, by accessing the Array.prototype and executing them with apply or call to change the context:

var argsString = Array.prototype.join.call(arguments, '/');

Edit: Since the original question asked almost 9 years ago was updated to use ES6 syntax, I feel the need to provide an ES6 answer now the language provides native constructs to handle this kind of situations.

The ES6 standard introduces the spread operator, which you can easily use to receive the arguments as an array object, for example:

function sum(...numbers) {
  return numbers.reduce((sum, value) => sum + value);
}

console.log(sum(1,2,3,4)); // 10

Applied to your example:

const getSearchFields = (...fields) => {        
  const joined = fields.join('/'); 
};

You can also use the spread operator to do function calls, let's say you have an array, and you want to call a function, passing each element of the array as an argument of the function call, now you can simply:

function sum(a, b, c, d) {
  return a + b + c + d;
}

var array = [1, 2, 3, 4];
console.log(sum(...array)); // 10

Also you can expect some arguments and have the rest of the arguments passed as the last parameter defined:

function processList(first, ...rest) {
  // ...
}

And there are more uses of the spread operator that go beyond the scope of this question, for example object copying, spreading arrays in arrays, etc...

Electrophilic answered 15/9, 2009 at 1:47 Comment(3)
'/' needs to be surrounded by bracketsPicrite
Nope, I'm using call, not applyDena
...correction, this might need to be the case when apply is called. You're using call. My mistake.Picrite
P
8

If you are using jQuery 1.2+, you can use $.makeArray():

Convert an array-like object into a true JavaScript array.

From the example in the question, just use this line

var args = $.makeArray(arguments);
Prostyle answered 3/3, 2014 at 19:46 Comment(1)
Just for records sake this works for me in jQuery 1.11.0Chui
C
5

arguments is not really an array.

try this:

var args = [].splice.call(arguments,0);
var argsString = args.join('/');
Civil answered 15/9, 2009 at 1:46 Comment(0)
E
2

The problem is that arguments is an array-like object (it has numbered properties mapping to the passed arguments and a length property), but it actually isn't an array.

In the old days, you could make it into a real array with Array.prototype.slice.call(arguments) (among other methods).

However, we're a bit luckier these days (depending on your supported platforms of course). You can either do...

const getSearchFields = (...args) => {
   Array.isArray(args); // true
};

...or...

const getSearchFields = () => {
   const args = Array.from(arguments);
   Array.isArray(args); // true
};

The first example is preferred because...

  • you get the normal array creation without an extra step in the function body
  • arguments is a magic variable (it's not defined explicitly, so where did it come from?)
  • it has funny behaviour with named args in non-strict mode (note that you should always 'use strict')
  • the first example has much clearer intent (the creation of an array of all arguments is explicit).
Engrave answered 24/4, 2018 at 11:25 Comment(0)
P
0

arguments is not a JavaScript array; it's a special object that doesn't have a join method.

Pibroch answered 15/9, 2009 at 1:45 Comment(0)
L
-1

If your are getting while posting http request in angular4 user HttpHeaders. Please check below answer. After usring HttpHeaders my issue is resolved.

this.headers  = new HttpHeaders({ 'Authorization': token1, 'X-IBM-Client-Id': 'ddddddd' });

values.join is not a function in the file http.es5.js Angular 4

Leveret answered 27/10, 2017 at 13:56 Comment(0)
R
-2

You have to make assignment to a variable for it to work.

var a = ['Wind', 'Rain', 'Fire'];

var myVar1 = a.join();

var myVar2 = a.join(', ');

var myVar3 = a.join(' + ');

var myVar4 = a.join('');
Ronna answered 13/5, 2015 at 18:28 Comment(1)
Your statement isn't correct and it doesn't answer the question.Engrave

© 2022 - 2024 — McMap. All rights reserved.