tbd_
tbd_

Reputation: 1258

How does join() produce different results depending on the arguments?

I can't quite understand why the join() call below produces different results, depending on the type of argument(s) provided.

Here's what I found:

var test = function() {
  var args = Array.prototype.join.call(arguments,"_");
  return args
};

console.log(test([1,2,3])) // #1: returns 1,2,3
console.log(test(1,2,3)) // #2: returns 1_2_3

Given join(arguments, '_'), shouldn't it produce a _ delimited string in both tests above? Why does #1 return a comma delimited value instead?

Upvotes: 15

Views: 1040

Answers (6)

Walter Macambira
Walter Macambira

Reputation: 2605

The result is different, because arguments is different.

On the first call (test([1,2,3]), you have one argument which is an array. On the second call, you have 3 arguments, each one being a number.

Array.prototype.join is meant to be called over arrays. It will stringify each of the items in the array.

In you your first case, your arguments "array" has only one member, which is an array itself. This argument will be stringfied. An array stringfied becomes exactly what is logged in your code.

Upvotes: 3

VLAZ
VLAZ

Reputation: 29002

In the first example you are not calling .join on the array but on arguments. That variable will be populated with an array-like object that has an array as first index, in essence, you are calling the equivalent of:

let myArguments = [[1, 2, 3]];

console.log(myArguments.join("_"));

instead of what you do (the equivalent of) in the second example:

let myArguments = [1, 2, 3];

console.log(myArguments.join("_"));

Upvotes: 4

Jack Bashford
Jack Bashford

Reputation: 44105

Because you're passing one argument which is an array - so it converts it to a string, then attempts to join it to the other arguments (there are none) so it just returns the string.

var test = function() {
  var args = Array.prototype.join.call(arguments, "_");
  return args
};

console.log(test([1, 2, 3]));
console.log(test(1, 2, 3));

You can solve this by checking if there's only one argument passed.

var test = function() {
  var args = arguments.length == 1 ? arguments[0].join("_") : Array.prototype.join.call(arguments, "_");
  return args;
};

console.log(test([1, 2, 3]));
console.log(test(1, 2, 3));

Upvotes: 3

CertainPerformance
CertainPerformance

Reputation: 370789

When you pass an array to test, the arguments object becomes an array of arrays, not a plain array of plain values. It's the difference between

arguments = [[1,2,3]];

and

arguments = [1,2,3];

When you call .join on an array of arrays, each inner array gets implicitly coerced to a string first, resulting in '1,2,3' - the values of the inner arrays do not get .joined by the delimiter, only the immediate children of the outer array get .joined by the delimiter.

Upvotes: 12

HRK44
HRK44

Reputation: 2762

The first one, first argument is [1,2,3] which is joined with the second argument, which is nothing -> output is [1,2,3].toString().

Second call, it's actually joining all the 3 arguments, resulting in outputting 1_2_3.

Upvotes: 3

Kobe
Kobe

Reputation: 6446

In your code, you only have one argument in the first example, that being an array. Joining a single element will remove the brackets:

var test = function() {
  var args = Array.prototype.join.call(arguments,"_");
  return args
};

console.log(test([1,2,3])) // args = [[1,2,3]]
console.log(test(1,2,3)) // args = [1,2,3]

console.log([[1,2,3]].join('_'))
console.log([1,2,3].join('_'))

Another way to look at this is to provide another array as an argument to test():

var test = function() {
  var args = Array.prototype.join.call(arguments,"_");
  return args
};

console.log(test([1,2,3], [4,5,6]))

Upvotes: 5

Related Questions