# String.prototype.join

**URL:** <https://es.discourse.group/t/string-prototype-join/1237>\
**Category:** 💡 Ideas\
**Created:** [March 5, 2022, 3:33am UTC](https://es.discourse.group/t/string-prototype-join/1237 "2022-03-05T03:33:42Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![pomle](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pomle/32/1261_2.png) [@pomle](https://es.discourse.group/u/pomle)\
**Post date:** [March 5, 2022, 3:33am UTC](https://es.discourse.group/t/string-prototype-join/1237/1 "2022-03-05T03:33:42Z")

</div>

The equivalent of `['a', 'b'].join(', ')` in Python is `", ".join(["a", "b"])`. My first impression of this, many years ago, was that this looked silly. However, I believe it to be a strictly better way of joining parts by a string.

I believe the String prototype is a more logical owner of a join method because the common denominator for things that can be joined by a string, is that they are iterable, and not that they are Arrays.

Since the advent of spread operator, joining iterables is trivial (`[...mySet].join(", ")`).

However, I think Python got this technically correct, and think it could be a useful addition to ECMAScript.

Polyfill implementation

```nohighlight
String.prototype.join = function join(iter) {
  return [...iter].join(this);
};

```

Example

```nohighlight
String.prototype.join = function join(iter) {
  return [...iter].join(this);
};

const myArr = ["a", "b", "c"];
const mySet = new Set(["a", "b", "c"]);
const myMap = new Map([
  [1, "a"],
  [2, "b"],
  [3, "c"],
]);

console.log(", ".join(mySet));
// a, b, c

console.log(", ".join(myArr));
// a, b, c

console.log(", ".join(myMap.keys()));
// 1, 2, 3

console.log(", ".join(myMap.values()));
//a, b, c

```

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [March 5, 2022, 3:57am UTC](https://es.discourse.group/t/string-prototype-join/1237/2 "2022-03-05T03:57:15Z")

</div>

Another option would be to put the `join()` method on all iterators (via the [iterator helpers proposal](https://github.com/tc39/proposal-iterator-helpers)).

---

<div class="post-metadata">

**Author:** ![pomle](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/pomle/32/1261_2.png) [@pomle](https://es.discourse.group/u/pomle)\
**Post date:** [March 5, 2022, 10:39am UTC](https://es.discourse.group/t/string-prototype-join/1237/3 "2022-03-05T10:39:39Z")

</div>

Maybe. I am thinking that joining all value together to a string makes only sense if everything is buffered already kind of. I like what you are thinking, but I feel like this is more suitable on the String prototype.

The only drawback I can really see, is that it is not possible to do `"1,2,3".split(",").join("-")` with the Python variant. But I am not suggesting `Array.prototype.join` is removed.

I think the most compelling reason to add `String.prototype.join` is if there is possibilities of performance improvements under the hood. But they might be possible, or is already done, in the optimizers using `[...myIter].join(",")`.

@theScottyJam, or what is your take on this?

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [March 5, 2022, 3:06pm UTC](https://es.discourse.group/t/string-prototype-join/1237/4 "2022-03-05T15:06:48Z")

</div>

I remember disliking the fact that Python's join method seemed to be flipped around, I never knew why they did it until you explained it here, and I can see the wisdom in that. But still, it's conceptually backwaords. You're "joining" the array (or iterator) together with a string. This means you're acting on the array/iterator, and the string is just a parameter. I don't believe Python has a way to arbitrarily attach methods to iterators, so the only way they can make `join` support all iterators is to reverse it and make `join` an instance method on the string, or, they could have just made join a static method on their list class (or some new iterator namespace) and added `join` to that and had `join` take two arguments, I would have prefered that over the reversal they did.

Anyways, to address some of your feedback

> Maybe. I am thinking that joining all value together to a string makes only sense if everything is buffered already kind of. I like what you are thinking, but I feel like this is more suitable on the String prototype.

I'm not exactly sure what you mean here. If it's able to consume an arbitrary iterator, then there's going to be no guarantee that it's buffered, even in Python's case.

```python
>>> f = open('./temp.txt', 'r')
>>> '\n===\n'.join(f) # This file object is not buffered. Python is reading the file as it joins.
'hi\n=====there\n'

```

> The only drawback I can really see, is that it is not possible to do `"1,2,3".split(",").join("-")` with the Python variant.

We won't need to worry about fluent-API support once the [pipeline operator proposal](https://github.com/tc39/proposal-pipeline-operator) gets through. You would be able to write that like this if you don't want to use the array version:

```javascript
"1,2,3"
  |> %.split(",")
  |> %.join("-")

```

> I think the most compelling reason to add `String.prototype.join` is if there is possibilities of performance improvements under the hood.

Adding it to the iterator prototype would cause it to have the same performance optimizations. For example, I would be able to write something like this, and the engine will be able to build the joined string as it consumes the iterator, without having to build an intermediet array.

```javascript
function* upTo(limit) {
  for (let i = 0; i < limit; ++i) yield i
}

// join() is being called on the iterator produced by the generator.
// It's not being called on an array.
upTo(100).join(',')

```

Of course, if we want to go this route, we would need to request that they add this function to the collection of functions they're adding to the iterator. Who knows, maybe functions like this could end up becoming a follow-on proposal instead of part of the core.
