Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 473
tbd_ Avatar asked Jun 17 '19 07:06

tbd_


6 Answers

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.

like image 191
CertainPerformance Avatar answered Oct 17 '22 19:10

CertainPerformance


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]))
like image 34
Kobe Avatar answered Oct 17 '22 20:10

Kobe


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("_"));
like image 20
VLAZ Avatar answered Oct 17 '22 18:10

VLAZ


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.

like image 40
HRK44 Avatar answered Oct 17 '22 18:10

HRK44


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));
like image 20
Jack Bashford Avatar answered Oct 17 '22 18:10

Jack Bashford


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.

like image 3
Walter Macambira Avatar answered Oct 17 '22 18:10

Walter Macambira