Array.prototype.join()

Straightforward until a null sneaks in — nullish elements become empty strings rather than the text "null", producing doubled separators that are easy to misread as a data bug.

Array methodES1 (1997)Live demo
Common call
items.join(', ')
Returns
a string; empty array gives an empty string
Replaces
a reduce that concatenates with a separator
Watch out
the DEFAULT separator is a comma, not an empty string
array.join([separator])
→ string

Demo

Live evaluation
Try:
Inputs
itemsstring[]items, comma separated
separatorstringseparator
Output
['a', 'b', 'c'].join('-')
'a-b-c'

The separator goes BETWEEN elements, never at the ends — so three elements produce two separators. A single element produces none at all, and an empty array gives an empty string rather than the separator or null. An empty separator concatenates the elements directly, which is the usual way to build a string from characters.

Parameters

NameTypeRequiredDescription
separatorstringno (',')Placed between elements. Defaults to a comma — pass an empty string to concatenate with nothing between.

Return value

string — All elements converted to strings and concatenated with the separator between them. An empty array gives an empty string.

Common patterns

Build a human-readable list
The most common use.
const label = tags.join(', ');
Concatenate with nothing between
An empty separator, not the default.
const word = chars.join('');
Build a path or query
Any delimiter-separated format.
const path = segments.join('/');

Examples

1. Dash separated
[1, 2, 3].join('-')
Returns
'1-2-3'
2. Default is comma
[1, 2, 3].join()
Returns
'1,2,3'
3. Empty separator
['a', 'b'].join('')
Returns
'ab'
4. null becomes empty
[1, null, 3].join('-')
Returns
'1--3'
5. Empty array
[].join('-')
Returns
''
6. Nested uses commas
[1, [2, 3]].join('-')
Returns
'1-2,3'

Pitfalls

1. null and undefined become empty strings
Not the text "null" — nothing at all. The result is two separators in a row, which reads like a formatting bug rather than missing data and is easy to skim past.
Doubled separator
[1, null, 3].join('-')
'1--3'
Filter first
[1, null, 3].filter(x => x != null).join('-')
'1-3'
2. The default separator is a comma, not empty
join() with no argument inserts commas. Code expecting plain concatenation gets commas everywhere — pass an empty string explicitly.
Commas appear
['a', 'b', 'c'].join()
'a,b,c'
Empty string
['a', 'b', 'c'].join('')
'abc'
3. Nested arrays use their own commas
An inner array is converted with its own toString, which always uses commas regardless of the separator you passed. The output mixes two delimiters.
Mixed delimiters
[1, [2, 3]].join('-')
'1-2,3'
Flatten first
[1, [2, 3]].flat().join('-')
'1-2-3'
4. Objects become [object Object]
join calls String() on every element, and a plain object stringifies to [object Object]. Map to a field first if you wanted something readable.
Useless output
[{n: 1}, {n: 2}].join(', ')
'[object Object], [object Object]'
Map to a field
[{n: 1}, {n: 2}].map(o => o.n).join(', ')
'1, 2'

When to use

Use it
  • Turning an array into a human-readable string
  • Building delimiter-separated formats like paths and CSV rows
  • Concatenating characters with an empty separator
Reach for something else
  • The array may hold null or undefined → filter first
  • The elements are objects → map to a field first
  • You need real CSV escaping → a CSV library, not join

Notes

Complexity
O(n) in the total output length
Return
A new string; the array is never modified
CPython impl
V8: Builtins-array-join.tq, with a fast path for flat string arrays
Memory
Allocates the result string
Thread-safe
Single-threaded; the source is only read

FAQ

Because an element was null or undefined, and join converts both to an empty string rather than to text. The separators on either side end up adjacent. Filter the array first if nullish values are possible.

[1, null, 3].join('-')   // '1--3'

History

ES1
join has been present since the first standard in 1997.