javascriptecmascript-6template-literalslanguage-specifications

Why do array functions work like tagged template literals and what can I do with it?


Just recently I found this to be working:

const str = "foo bar";
const arr = str.split` `; // <- no parens
console.log(arr);
// -> ["foo", "bar"]

It seems like the split prototype is a tagged template literal. I also saw this working with other array functions like indexOf.

Is there a specific reason for implementing this behavior? Can I do something with it that I could not do before or can I solve some tasks in a simpler way?

It seems that there has been some effort put into the implementation, and every use-case that I can think of would just overcomplicate things. It seems to me like a waste of time to make it possible. Or did it come at zero cost? If so: How?


Solution

  • You can call any function by using it as a template tag.

    Template tag functions receive the following parameters:

    1. Array of static string parts
    2. to infinity. Substitution values

    So, your call unwraps to:

    const arr = str.split([' ']);
    

    String#split() expects its first argument to be a string or regex. An array is neither of those, so .split() coverts it to string by invoking its .toString() method.

    Array#toString() returns the array's elements separated by commas. In case of a single element, it returns the element converted into a string.

    As ' ' is already a string, it is returned, and used by .split() to split the input string.


    Although there are some cases that can work like that, this usage (using functions as tag functions that wasn't designed for that) is discouraged, as it is unreadable, less performant (creates additional arrays, etc.) and saves only 2 characters (` ` instead of (' ')), however, it is used by some minifiers and obfuscators.