JavaScript, EcmaScript 6
I will be focusing on features/snippets of/from ES6 standard in this answer. Some snippets require knowledge of topics previously presented, so you may want to read this bottom-to-top.
Length 17 snippet:
"𠮷".codePointAt()
More Unicode support! .codePointAt()
is a Unicode-compliant version of .charCodeAt()
. For example, if you were to take
"𠮷".charCodeAt()
you would find 55362
. This might seem right, but if you convert it to hexadecimal, you would find that it corresponds to U+D842. Looking on Graphemica, we can see that the character is actually U+20BB7. U+D842 is one of the two surrogates that makes up the UTF-16 representation of that character.
But enough of these details: the point of .codePointAt()
is to find the actual Unicode point of the character. "𠮷".codePointAt()
is 134071
, or U+20BB7—the correct result. Finally Unicode lovers can use JavaScript!
Length 16 snippet:
/^.$/u.test("𠮷")
Another nice feature of ES6 is proper Unicode support! If you tried this code in ES5:
alert(/^.$/.test("𠮷"))
You might be surprised to find that the answer is false
! The problem here is in JavaScript's default encoding, UTF-16: characters above U+FFFF are actually represented as 2 chars, called "surrogates". (You can learn more about this on Wikipedia.) In order to fix this, you need a more complex regex:
alert(/^(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|.)$/.test("𠮷"))
ES6 introduces the u
flag on regexes. When u
is set, characters above U+FFFF are still captured as a single char. So /^.$/u.test("𠮷")
returns the correct result: true
.
Length 15 snippet:
String.raw`q\n`
Back to tagged templates! ES6 comes with a function all set up to be used as a tag: String.raw
. This returns the raw text you typed in the template (replacing interpolations with their values), so the above snippet is equalivalent to "q\\n"
.
Length 14 snippet:
Number.EPSILON
As you may know, JavaScript's numbers are not arbitrary-precision; they have exactly 53 bits of precision. This can cause problems when trying to add decimal numbers:
var point3 = 0.1 + 0.2;
alert(point3 === 0.3); // false!
The problem here is that neither 0.1
nor 0.2
can be represented exactly in binary, and when adding them together, the least significant bit is rounded the wrong way, resulting in 0.30000000000000004
instead of 0.3
.
Number.EPSILON
was added as a workaround to this problem; it is equal to 2-53, the smallest number that can be added to 1 without rounding back down to 1. We can use this to create a new equals function:
equals = (num1, num2) => Math.abs(num1 - num2) < Number.EPSILON;
alert(equals(point3, 0.3)); // true!
Hooray for ES6!
Length 13 snippet:
s=>s.split` `
What is this? A function call without parentheses? Actually, it's another use of template literals: tagged templates! But what is actually happening here?
When you tag a template with a function, it calls the function as usual, but it passes in the arguments a little differently. Take this example function:
function parseMe(strings, name, age) {
alert(`Your name is ${ name } and you are ${ age } years old`);
console.log("We don't need these strings:", strings);
}
myName = "Bob";
myAge = 123;
parseMe `Hello, I'm ${ myName } and I've orbited the earth ${ myAge } times.`;
This alerts Your name is Bob and you are 123 years old
. Why? When calling a function with a tagged template, JavaScript passes each ${ }
value as a separate parameter, groups the strings into an array which is passed before everything else. So you're really calling parseMe
like this:
parseMe( ["Hello, I'm ", " and I've orbited the earth ", "times."], myName, myAge );
Cool, right? Now back to the original snippet. Now we can see that it could be written like this:
s=>s.split([" "])
.split
coerces its argument to a string before splitting. The string representation of [" "]
is " "
, so the function could be written yet another way:
s=>s.split(" ")
And this simply splits the text on spaces, which splits it into words. Isn't ES6 awesome?
Length 12 snippet:
n=>`Hi
${n}`
Introducing...template literals! Yet another super-helpful ES6 feature. These act like strings for the most part, but you can include newlines without escaping them. Not only that, but you can also use interpolation! If you run the above function with input "JavaScript"
, it will output this:
Hi
JavaScript
Length 11 snippet:
[a,b]=[b,a]
Tired of using that old var tmp = a; a = b; b = tmp;
trick to swap variables? Now you don't have to! Using destructuring, you can swap those two variables quickly and concisely with the above statement.
Length 10 snippet:
[a,...b]=b
Destructuring! Yay! This is one of the cooler features of ES6. You can use it to do many things that would have taken a lot more bytes in ES5. For example, this is what the above statement corresponds to in ES5:
a=b[0],b=b.slice(1)
Actually, a=b.unshift()
works too, but consider when you want to grab the first three items:
[x,y,z,...b]=b
x=b.unshift(),y=b.unshift(),z=b.unshift()
Or if you don't want to change the value of b
:
[x,y,z]=b
x=b[0],y=b[1],z=b[2]
As you can see, destructuring is shorter, more readable, and just all-around better.
Length 9 snippet:
new Set()
Another useful data-type that JavaScript now supports is Sets! You can create a set like so:
var myArray = [1, 3, 6, 3, 2, 1];
var mySet = new Set(myArray);
// Set [ 1, 3, 6, 2 ]
As you can see, creating a Set out of an array removes all duplicate items. You can turn it back into an array with the spread operator:
myArray = [...mySet];
// [ 1, 3, 6, 2 ]
You can also use this trick on strings:
var myString = "Hello, World!";
var mySet = new Set(myString);
myString = [...mySet].join("");
// "Helo, Wrd!"
Keep in mind that the Set constructor must be called with new
, and only works on the first argument. For example, this won't work:
var mySet = new Set(1, 3, 6, 3, 2, 1);
// TypeError: 1 is not iterable
You can learn all about Sets on this page.
Length 8 snippet:
(i=0)=>i
You probably understand what this example is: default parameters! JavaScript ES5 is really horrible with default values. Usually you can get away with this workaround:
function f(i) {
i = i || 0;
return i;
}
However, this resets i
if it is anything falsy (false
, 0
, ""
, null
, or undefined
). To just do null
or undefined
, you have to be much more verbose:
function f(i) {
if (typeof i === "undefined" || i === null)
i = 0;
return i;
}
But ES6 contains a new syntax for default values! Now you can shorten your code to this:
function f(i = 0) {
return i;
}
Or in ES6 arrow notation, f=(i=0)=>i
. When given an input, this just returns the input, but when called with no input, it returns 0
. This is very helpful in uncountable scenarios, and possibly one of the best additions of ES6.
Length 6 snippet:
Symbol
JavaScript now supports Symbols! A symbol is created with Symbol("foo")
, and every symbol created is different: Symbol("foo") !== Symbol("foo")
The only way to keep a symbol is to assign it to a variable: var sym = Symbol("foo"); sym === sym
One of the most useful Symbols is Symbol.iterator
. This is a Generator which is used whenever you iterate over an object, whether with for-in loops or the ...
operator (see below). For example, the following code defines an iterator for all Number objects:
Number.prototype[Symbol.iterator] = function* () {
for(var i = 0; i < this; i++)
yield i;
}
Now [...6]
returns [0,1,2,3,4,5]
! Aren't generators fun?
Length 5 snippet:
const
This for a change is exactly what you've guessed! Its a new variable declaration syntax used for creating constant variables.
const a = "foo";
Now a
's value is fixed, any attempt to change it will lead to a SyntaxError
(cos JS!). Not only that, if you skip the assignment part while declaring the variable, that will also lead to a SyntaxError
.
const a;
// Exception: SyntaxError: missing = in const declaration
const a = "foo";
a = "bar";
// Exception: SyntaxError: invalid assignment to const a
Length 3 snippet:
...
Default arguments ? Java ? Nope! This is the new spread operator and it does exactly what it says.
For instance, you want to spread your array variable A
into another array B
in the middle alongside other things:
var B = [1, 2, 5, ...A, 8, 0];
That simple!
You can even do this with function calls or arguments.
function foo(a, b, ...c) {}
is a function whose first argument goes in a
, second goes in b
and rest all arguments (third, fourth ...) go in as an array in c
.
Now if you want to call that function and all your arguments are in the array A
, you can do it like
foo(...A);
Length 2 snippet:
=>
Think that I put greater than or equal to sign the wrong way ? Think again! Think ES6!
This is one of the best features of ES6 - Fat arrow function . Apart from reducing a lot of bytes while defining a function (var a=_=>_+_
instead of var a = function(_){return _+_}
), arrow functions also change the behavior of this
so that you don't have to bind
the function again and again.
Length 1 snippet:
*
Multiplication ? Nope! Remember ES6! The *
keywords is part of one of many syntax sugar + features of ES6 - Generators. This is added to the function
keyword to make the function a generator function.
Factoid
ES6 adds a lot of useful syntax sugar and features into the language inspired by a lot of other languages.
The most useful fact about ES6 is that due to the added syntax and features, it performs much better than ES5 (current generation JS across all browsers) in terms of code-golf.
The final spec for ES6 was finalized in June 2015, and all major browsers (except IE) have enabled most of the new features. You can check this page to see which features your browser supports, as well as all major browsers and other environments.