ECMeowScript–what’s new in JavaScript explained by cats
(upbeat electronic music) - Hi.
Good morning, good evening, depending on where you are. This is such a great opportunity for me to give this talk to you at many different times zones together.
And this is my assistant, Jamie.
(laughs) (indistinct) Here Jamie (indistinct).
All right! I'm going to talk about the things you may or may not know in JavaScript with a bunch of a cat images and puns, and a little bit about myself.
Again, my name is Tomomi Imura and I work at Microsoft. Actually, I just joined the company this Summer, so I'm new. And then, we're giving this talk from my tiny little apartment in San Francisco, so sorry about all the clutter in my background. And my expertise is Cat-as-a-Service.
What is Cat-as-a-Service? Well, obviously I made it up.
But you might have seen some of my past works. Like HTTP Status Cats, something that I made a long time ago.
And this is my IoT project, Raspberry Pi KittyCam.
This is actually my most popular GitHub repo. And some doodles.
So I occasionally tweet doodles, like tech doodles, so if you're interested, do follow me. (laughs) All right, so let me talk about JavaScript. Which is actually an ECMAScript, which is a standard script language specification created to standardise JavaScript to help foster multiple implementations.
And I'm gonna explain ECMAScript with cats! So, I called this ECMeowScript! (exclaims) I know it's silly.
(laughs) All right.
Let's begin with ES6, 'cause I have to, you know, I have a lot of contents to cover here.
So it was five years ago when ECMAScript 2015 the sixth edition, that's why we call it ES6, was finalised.
And this update brought us a significant amount of new syntax and features to help you write complex code better and simpler.
And here's some, you know, new features and syntactic sugars here.
So we've got arrow functions.
And const and let, that's a block scope, and compared with var as a function scope in ES6. And template literals, this is something like, you can have this dollar sign symbol to have variables within the string, which is pretty convenient.
And other things like promises, iterators and generators, and for..of iterator.
That's quite convenient for looping through there, right? Kinda like for..in for object.
And class definition inheritance.
Destructuring assignment, I'm gonna explain that later too. Rest parameters and Spread operators.
And Set, Map object.
And also, we got internationalisation API.
Technically this is a different spec, it's specified in ECMA-402.
And, you know, the language specification is actually in ECMA-262.
But I thought it was really worth mentioning here, because it was introduced around the same time. And yeah, if you're interested in learning more about this special, international DateTime format, I wrote a blog about this last year.
Because yeah, it was quite interesting time, I mean, it was a significant year, significant time, last year in Japan.
Because they've got a new emperor, it means a new imperial era has begun, so I wrote about this.
All right.
So, there are a lot of new features has been introduced and I can't really explain whole things, but let me just talk about some practical ones here. So something you can use right now.
Let's see.
So, for example, we've got this array called "cats" and this array has objects, and each object has name, Jamie, you just saw Jamie, and type, img.
And Leia, Leia's another cat I have.
And Alice, it's my friend's cat.
Anyways.
So, let's take this given array of object.
And what you need to do here is, let's say you had to create a new array that contains only cat names, actual values of the cat name: Jamie, Leia and Alice, how would you do? So with ES5, you'd probably do something like this, just loop through the original array using maybe for..each or just a for loop.
And then, let's say you create an empty array first and at each iteration, you might just push the value of cat's name into that array.
That's cool.
But now we can rewrite this with ES6 using array.map() function.
I mean, you don't have to rewrite, but you can. But before that, let me just quickly explain what it is. So this is a different example.
Array.map() creates a new array by basically tweaking the data in the original array, and that creates and returns a new array here. And this .map() function has its built-in iterator, so you don't need to do a for loop by yourself. So in that case here, you got a function, so this .map() calls a callback on each element in an array and you get this new array that contains doubled number two, four, six, eight, because we return each element multiplied by two here, right? Okay, let's go back to the cat example.
So with the array.map() function, you can return a new array, catNames, like this. Cool, right? And also, ES6 introduced arrow function, so you can rewrite that code that uses array.map() with this array function like this.
So let me toggle.
So this was before: you got cats.map() and function, and it has parentheses, an argument and the return cat.name. Now you can rewrite just like this.
Slightly shorter, because you got rid of the word function and replace that with arrow. It's not replaced in the same place, but using the arrow now, it's shorter.
But you know what? You can even write this shorter.
So the arrow function allows you to achieve it more concisely and clearly, like this.
So, let me toggle it again.
This was before, and now it's just one line. So you notice, there's no parentheses here. So you can omit the paren when you have only one argument.
And also notice here.
Now you don't have a squiggly bracket, or maybe curly braces if we wanna call it, you can get rid of this too when you only have the one line of code that returns a value of the statement.
So yeah, now it's super short.
It's just one line.
Cool.
Alternatively, you can achieve the same result using destructuring.
So you can unpack the properties from objects and create it into distinct variables here. So notice it had a squiggly bracket here.
And here's another example.
So, forget about this cats array for now, and let's see a cat object, this cat01 object that has name, type, img. It doesn't matter what's in, but let's see this object here.
And then, basically, when you wanna create new variables and assign to those values, you can write like this, with using destructuring here. And this is something you can take a look at, the right-hand side here.
So this is how we used to do with ES5, so you assign each one of those.
You know, so I found this particularly useful when I tried to get some sort of data from, let's say, when I call some API, right.
And that API returns a chunk of JSON data, and I wanna get just some of those datas.
We can do this using destructuring, so I thought it's really useful.
Next one is spread operator, AKA "three-dots". So in this case, let's say you got catNames array: Jamie, Leia, Alice.
And you wanna add this array into another array, which already contains some values: Yugi and Snori. You can use these three-dots, so, ...catNames, which unpack the element into an array.
So that resulted newCatNames array, it's just a single one dimensional array, with full values.
And this is really something I really find useful and I like it, so let's assume another usage. So concat, con cat, that's one stupid cat pun. (laughs) So anyway, when concat two arrays, we can use concat method, but with using these three-dots you can just do that easily.
Well, maybe just still the one line of code, but it's a different way to do that with ES6. And you can do converting string to array, now finding the largest with Math.max(), Math.min() to find the smallest, and you can just use this Spread operator there too. And it has so many, you know, pretty creative, useful ways to do.
And I, again, I found this really useful, so I wrote a blog about this.
So if you're interested in reading more, there's a URL here. And now, JavaScript has map object, but this is different from the array.map function I was talking about earlier, it's a map object. So yeah, now you can create a JavaScript HashMap so you can cat-alog (giggles) the collection data. So, you can of course use good old objects. That still works, of course.
But you know, this map object, you can use get and set methods to access the values, and also has, too.
So you can create HashMaps, and I think that looks more intuitive.
Yeah, so, I think I covered a lot.
Well, it wasn't everything, but it was a lot of stuff. But let's move on to ES7.
So ES7 was relatively smaller updates, got a few. And I wanna talk about exponentiation operators. It's two stars, but I interpret this as two paws, like cat paws.
Those paws are Leia's paws, my cat.
Anyways, two paws.
Well, that does same thing as Math.pow(), P-O-W not P-A-W.
I know when I say paw and pow they both kinda sound the same, but nah, anyways. So yeah, it's same thing as Math.pow(), which returns that base to an exponent power. So let's say, when you get a Math.pow(), it has "3, 2", that returns 9, right? So, same thing, when you get "3 ** 2", that returns 9. It's like three times three, right? So...
And another one is array.includes().
So this returns a boolean.
Let's say you get a coatColors array here: solid, bicolor, tabby, calico, and stuff.
And when you wanna check if tabby, the string tabby, is included in this array, you can just use this .includes() method here. So, coatColors.includes() and tabby, and that's true. And neon is not there, so it returns false. So previously, with ES5, we already have .indexOf() method here and that returns index, but now we got boolean. Of course, we could get a true/false value from index, though, by checking if it returns -1 or not. But, you know, it's really nice and handy to have actual boolean function, right? Let's move on! ES8.
So we get a sizable updates with ES8.
It's async and await, padStart() and padEnd(), trailing commas, I'm gonna explain those three later, and we got object.entries(), that returns an object with key-value pairs in an array as an array of array.
What? (laughs) And object.values(), and shared memory and atomics. So let me talk about async and await.
So async and await is basically a syntactic sugar on top of promises.
But, you know, that makes your code more readable. And I have this silly little example here, using something called Litter Robot.
So this is a automated litter box that I have at home. (laughs) Anyway, so what it is, again, it's automated litter box. It has sensors, so it knows when a cat is in and doing business and after cat finish and just leave the box, it starts a cleaning cycle. So here is pseudocode of this operation.
So yeah, this can be written as async and await function, right? Because this Litter Robot, this operation, need to await until cat finish the business. So await cat.poop() and then clean().
And notice this await keyword, we have async here, right? So the await keyword is only valid inside of this async() function, so you need that. But, what if you write this synchronously? Like, without async() and await.
Well, what can it poo-sibly go wrong? (laughs) Yeah so, well, you can guess, I think clean cycle might begins when cat is still inside, right? So it's going to be a big mess.
Whoops.
All right, let's go on to this next example here, string padding.
So we got two methods: .padStart() and .padEnd(). So that allows you to pad a string at before and end. So let's say get the one-character string here. Well, it's a box.
Well, it's a emoji, it's Unicode, but let's assume this is a character and you wanted a pad in the beginning of the string, and you wanna make it four characters long, total. And you can set any character in the padding, so in that case, you wanna pad with kittens, yay. So in that case, the box, oh this is actually wrong, sorry, it's a box but it's supposed to be a boxStr. boxStr.padStart.() and a 4, it's four characters total, and a character you wanna pad with.
In this case, cat.
Well, this cute example is cute but it's not so practical, so let me give you a better practical example here. So let's say you want to categorise some sort of file names like this one, and instead of naming this file "5.jpg", you wanna have "0005.jpg".
You can use just a .padStart() like this, so that's pretty convenient.
And .padEnd() works a similar way, in this case it adds zero after, like "5000", but that's not what you want in this particular case scenario.
And yeah, yeah, this method actually works for right to left string as well.
And yeah, I use this example, like Arabic example, although I have no idea, I can't read, but I just got the Google Translate to get that. So you can use Arabic and Hebrew and all those languages as well.
And this is probably the reason why we don't call these method names .padLeft() and .padRight(), right? So by calling like start and end, it makes it universal, which is cool.
Another example is a trailing comma.
So this is not something new that you have to know, or memorise, or anything about.
That basically is something that used to cause the error is no longer causing the error for you. So yeah, comma and you're fine, you don't get a error, yay.
Now some example here.
So actually, even in ES5, we are allowed to use a comma in object literals, but now with ES8 we can use parameter list and calls like this one: makeFood('tuna', 'salmon',). And we can do that, it's fine.
It's just more convenient, 'cause when you wanna edit your codes later and add more values, I mean, more arguments and stuff, you can do that, right.
Or just, you know, just leave it why not? (laughs) All right, go on, ES9.
And there's some updates with ES9.
So it got Spread and Rest properties, like three-dots I was talking about earlier but you can now use with objects.
Cool.
And regular expression improvements, asynchronous iteration and promise .finally(), so got .then(), .catch() and .finally().
Well, I didn't really find a good cat joke, so move on. ES10. (laughs) Okay, so we got some stuff.
I'm gonna explain those first two later.
But we got something like object.fromEntries(), something like transforms lots of key-value pairs into an object.
We've got the JSON.stringify, that's like a bug fix. So that fixes some issue around Unicode.
And another one's like a better and faster array.sort(). So again, this is not something you have to worry about anything, it's a improvement. So apparently v8 used to rely on a QuickSort implementation for array.sort() function, but now it's moved to this more stable and faster algorithm called TimSort, which is a hybrid of Merge Sort and Insertion Sort.
Yeah, so, better algorithm means the faster, more stable, yay algorithm! All right.
So yeah, let me explain about .trimStart() and .trimEnd(), it's string.trimStart() and .trimEnd().
So chewy.com sells these grooming bags that makes it easy for you to trim cat's claws. (laughs) I don't know if this works well, I think my cats will still freak out.
But cat's in a bag and you can .trimStart(), (laughs) snip snip, you can trim cat's claws from paws.
So, well, pretty much the name indicates and you can guess what it is.
So .trimStart() method removes whitespace, so trims, from the beginning of a string.
So yeah, when you get some string with whitespace, like ' meow', and another two whitespaces, and when you have .trimStart(), you can get rid of the whitespaces in the beginning of the string.
And, you can guess, this is .trimEnd(), yay! (laughing) Yeah, so yeah, as you guess that, so .trimEnd() works that way, it trims off these whitespaces from the end of the string.
(laughs) And array.flat() and .flatMap().
(laughs) I can watch this forever.
Well, as you can pretty much guess what it is. Array.flat() method, that flatten an array. So let's say you got this colours array.
It's multidimensional, so you get a bunch of cat colours, had some black, grey, orange, all the mono-, uni- colours, one-colors array, and within this one-color array has orangy array, so orange and light orange, so three arrays total here. But when you get colors.flat() and no argument, it flats just one level.
So now it has three arrays, actually two arrays inside of the one, now get black, grey and array of orange, light orange, and bicolor and calico here.
And if you apply this method again, like colors1.flat(), you can flatten another level to make it flat too. Or, you can use this optional depth level as an argument. So if you apply this 2, that .flat(2), in the original colours array, you can flatten the whole thing.
And the .flatMap() method is somewhat similar, so it first maps each element then flatten the result into a new array.
Finally, the latest one, ES11, is 2020.
So we get BigInt, globalThis and a lot of stuff. I'm actually still learning what it is in, so I can't really, to be honest, explain the whole thing, but let me talk about BigInt after this.
But globalThis is like, you know, when you write JavaScript you can write it for web, I mean define it, right, for the browser.
And you got global object, like window and self and maybe frames too, but in Node.js you got only global.
So this globalThis property provides a standard way of accessing that global this value.
And you got some dynamic import and nullish coalescing operator.
And this is something cool, I won't explain this in these slides, but basically when you use these two question marks to access falsy values.
You used to use something like, I don't know, maybe using two pipes, or, to get falsy values, then something can be null or undefined.
But by using these two questions you can avoid some unexpected falsy values like, you know, false or just null, and things like that. And optional chaining is something similar that you can use it when chaining to handle nullish values. And we got something like .matchAll() method. That's something using regular expressions and things like that.
But let me explain BigInt with BigCat, yay.
(laughs) So JavaScript can represent number printer and can represent up to 2, to the power of 53, minus 1, that's what it is.
And you can actually write this as Number.MAX_SAFE_INTEGER constant here.
And now we got a BigInt object which can represent a larger number than that. So now we got two types of numbers now, just regular Number and BigInt.
So we got Max the cat and BigCat, n.
What is n? So, to use a BigInt, we use the suffix n at the end of that number.
So let's say you got max numbers using the expression Number.MAX_SAFE_INTEGER, so that's the largest number possibly accessed, and you can increment by one, max++, like this. It does increment once, but when you keep trying to increment again and again, it just doesn't work that way.
But you can use n.
You can increment by one as many as you want. So let's say the largest number here, 9007199 blah blah blah 2n, and increment by one.
So now he's at 0 blah blah blah blah and 993n. You can do that again, and 900 blah blah blah and 4n. And so on, so forth.
Apparently one of the most known example of this is, example of a large number you might wanna access with JavaScript, is a Twitter ID.
Yes, we tweet a lot, right? There's so many, oh my gosh.
And when you were using a Twitter API and tried to access Twitter ID, well, it already exceeding the largest number we could access. So developers needed to have some sort of work-around, basically by using a string version, right. But, looks like we can use the BigInt now.
Cool.
All right, so, (laughs) well, I'm basically running out of time and running out of cat puns, so I'm ending this presentation im-purr-fectly without explaining more stuff (laughs), but I hope you're all feline great about ES.next. Thank you so much, and you are paw-some! (upbeat electronic music)