简体   繁体   中英

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?

This is nothing special about the .split method, this is just how tagged template literals work. You can tag a template literal with any function, and it will be given as its first argument the parts of the template string outside of interpolation blocks. For this case that would be the array [" "] which then is used as the first argument for .split (after which point [" "] is converted to a string: " " ).

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.

String.prototype.split isn't actually designed to work with tagged template literals.

When you call split with a tagged template, the first parameter passed to the function is an array of strings in the template, so

str.split` `;

is equivalent to

str.split([" "]);

. The array only has one string and there are no more parameters because there are no placeholders ( ${} ) inside the template literal.

The spec says that the split method first converts the first argument to a string and then works with it, so

str.split([" "]);

is equivalent to

str.split(" ");

.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM