ES6: The Right Parts Tag Functions
Transcript from the "Tag Functions" Lesson
>> Kyle Simpson: So let's talk now about an extra feature that's included with interpolated literals. That is probably not terribly self-obvious what this is or what it's for. It is possible for me to put an expression directly in front of the interpolated literal. And that expression will act as, essentially, a function call.
[00:00:33] So you're thinking about what is the foo function? It would be a function that we would have to define. And you might assume that that function would receive the interpolated string literal as its argument. It's not really quite that, it's sort of like that but not quite, okay?
[00:00:52] So let me talk to you about what this foo function would do. This foo function is going to receive as its first parameter, as its first argument. By convention, we like to call it strings. I mean, you can call these whatever you want. But by convention, most people call it strings.
[00:01:07] Cuz what it is, is an array of all of the string literals from here. So it is gonna be an array that includes that string, and that string.
>> Kyle Simpson: And that string, and that string, so it's gonna have four string values in it, okay? It's an array of four string values.
>> Kyle Simpson: The next thing that we would get, obviously, we're gonna get these values in, you might think we would get a values array. For some crazy reason, they decided not to collect all the values up into an array. So what you actually get is value1, value2, value3 all the way out to however many values that are actually were, which is stupid and nobody wants to deal with those individually.
[00:02:02] So we all just collect them up into a values array using the ...gather operator. So virtually, all of these are called tag functions. Virtually, every tag function you find, the signature will look almost identical to that call strings, and then ...values. Obviously, you can name them whatever you want, okay?
[00:02:23] But what's the purpose of this function? Well, I can do really evil stuff like I am evil. If I return a different value for example that string and we ask what's in message, what do you think is gonna be in message? The string, I am evil, has absolutely nothing to do with what we passed in.
[00:02:42] I don't think it's a good idea, but you can. The point I'm making is that the tag function serves kind of like a preprocessor. It's almost like a macro, it preprocesses the string before it's finalized.
>> Kyle Simpson: Which is gonna allow you to do some, actually, very interesting things, okay?
[00:03:02] Before we talk about the interesting kind of stuff that we can do with them, let's just think about what's the very simplest approach for me to construct these things together. For example, let's observe that the strings array is gonna have four values in it, how many values are gonna be in the values array?
>> Kyle Simpson: Three, right? Four strings, three values. Even if we had an expression at the very beginning of our literal, there would still be an empty string in the strings array there. And even if we had an expression at the very end, there would still be an empty string there.
[00:03:43] So it will always be the case that the strings array has one more value than the values array. That is an invariant, it will always be true or always be one more string than there is a value. So you can probably realize if I had four strings and three values, what do I need to do to them?
[00:04:01] Loop over them and interpolate them, right? Concatenate them together.
>> Kyle Simpson: So the pass through version of foo that is the version of foo that acts as if it's not even there. It's to simply loop over the strings array and interpolate in the values, totally untouched. So let's write that logic, we'll have a string that we start out as empty.
[00:04:30] We do a for loop, for (var i=0; i<strings.length; i++). Now, what we're gonna do is you're gonna say if (i > 0) that is I'm already done the first string. Then I wanna include str += values[i- 1]. So I'll include values of 0 after I've done strings of 0 let alone strings of 1.
[00:05:03] And then I'm going to include,
>> Kyle Simpson: Strings of i. Finally, return the string.
>> Kyle Simpson: So this is the most basic, simplified kind of pass through template tag function that you could define.
>> Kyle Simpson: You following me?
>> Kyle Simpson: Just to test it, we'll grab that, come over here to the browser and run it, msg.
[00:05:38] There, we got the same message, okay?
>> Kyle Simpson: But let's do something slightly more interesting. How about in a case when we're gonna include a value, what if we did something like this? What if we said if (typeof values[i-1] == "number")?
>> Kyle Simpson: What if we,
>> Kyle Simpson: Did some formating of it?
>> Kyle Simpson: For example, gave it 2 decimal places.
>> Kyle Simpson: Do you see what I did there? So I'm checking one of those values. If one of those values comes in as a number, I wanna format that using the toFixed method, which gives me rounded to 2 decimal places with zero-padding on the right if I need it.
[00:06:36] Let's try it now.
>> Kyle Simpson: You spot the difference? Now, we formatted our currency correctly. So I could call this tag function currency for example, okay? And there's lots of more sophistication that you could probably start to envision for what you might do in terms of formatting. Either strings or the values that are being interpolated in, or in both in all kinds of different ways.
[00:07:10] As a matter of fact, people have already written hundreds of different tag functions. There are libraries that include all different manners of tag functions that do all different kinds of things that you can think of [COUGH] to do various formatting. For example, internationalization or localization of times and numbers.
[00:07:31] Or swapping in terminology like we said with internationalization, it's all different kinds of things that you could do. So basically, what you end up writing is this code, that library utility is written once. But anywhere in your code, you just say currency. Instead of telling it how to do all the formatting of the currency, you've abstracted that away, what you have is a declarative string.
[00:07:59] You say I want my string to be formatted with currency, or I want my string to be formatted with internationalization, or I want this string to be formatted with localization.
>> Kyle Simpson: So it's a declarative form to hide or to separate out the imperative logic of how to do the processing from the usage of it.
>> Speaker 2: Is there an easy way to chain them?
>> Kyle Simpson: The chaining doesn't happen at the call sign, the chaining happens through regular function composition techniques. So you could take two tag functions and chain the two together. But that would be through function composition, not at the call sign.
>> Speaker 3: [COUGH] If orderNumber wasn't a string, how would it know of the difference?
>> Kyle Simpson: It wouldn't, like I said it's just a simple example,
>> Kyle Simpson: To point out the types of things that we could do, okay?
>> Kyle Simpson: As a matter of fact, people have gone really far with this.
[00:09:29] Somebody got the bright idea, what if I make a tag function that allows me inside of an actual standard template literal to interpolate all of that HTML syntax and do the same thing? So they made a tag function for JSX. So now, you can use JSX and all you gotta do is wrap backticks in the JSX tag function in front of it.
[00:09:49] And now, it's standard and doesn't need any transpolation for example.
>> Kyle Simpson: So there's all kinds of sophisticated things that you can envision doing with the preprocessing on your strings.
>> Kyle Simpson: One of the guys that's on the committee, Alan, he was the former editor of the editor of the ES6 spec.
[00:10:11] His favorite usage of this is to use these to create regular expressions that you can do like whitespace, and other fancy stuff like comments. So you can make your regular expressions as a template literal instead of in the regular expressions syntax, which is a lot more limited. [COUGH]
>> Kyle Simpson: Okay, any questions about that general process of looping and interpolating with the string function or the tag function?