JavaScript is evolving. It’s an exciting time to be involved with this ubiquitous language of the web. Every year, we get exciting new features landing as part of the language. Let’s explore the freshly released features that were part of the 2019 ECMAScript specification. We’ll also briefly explore the process of how new features get proposed and added to the language, as well as the leading contenders expected to land in ES2020.
2. "Any application that can be
written in JavaScript, will
eventually by written in
JavaScript."
- Jeff Atwood, Co-founder of StackOverflow
2 / 48
3. We are 10.7 million developers
worldwide.
Together we support over 4.1 billion
users of the web.
3 / 48
4. Me, back in the day
Arrays
for (var i = 0; i < students.length; i++) {
newStudents.push(transform(students[i]));
}
Strings
...we write JavaScript very differently now.
var message = name + ', You have $' + dollars + ' in your account.
4 / 48
6. What we're talking about
ECMAScript, a brief, not at all complete, history
So, what is new in ES2019?
How do proposals turn into features?
ESNext proposals
6 / 48
8. Mocha is born
Brendan Eich creates
Mocha in 10 days
Java is really new and
trendy. JavaScript is
marketed as the
lightweight cousin.
Eventually renamed to
JavaScript in December
1995
8 / 48
10. ECMA
Netscape approaches the European Computer Manufacturers
Association.
JavaScript and JScript are implementations.
The spec is called ECMAScript.
ECMAScript 1 released in 1997.
10 / 48
14. Array.prototype.flatMap
With map() every element is translated to exactly one output
element.
With flatMap() every element can be transformed into a variable
number of elements.
14 / 48
15. Working with data
// Folder = { files: [] }
const folders = [folder1, folder2, ...];
const toFiles = folder => folder.files;
// Alternative
const result = folders.map(toFiles).flat(1);
const result = folders.flatMap(toFiles);
// result = [file1, file2, file3, ...];
// Before flatMap, not performant
const result = folders.reduce(
(acc, folder) => acc.concat(folder.files)
, []);
15 / 48
25. The TC39 proposal process
Technical committee 39 of ECMA International
ECMA 262 specification
Members are implementers that send delegates
Committee meets six times a year
A new process was defined after ES4 was abandoned, and ES6
was a massive release that took 6 years.
25 / 48
27. Stage 1 (Proposal)
Identified champion or champions who will advance the
addition.
Describe the problem or requirement
High level API
Potential concerns have been identified
27 / 48
28. Stage 2 (Draft)
Initial spec text
Incremental changes expected
The committee expects the feature to be developed and
eventually included in the standard
28 / 48
29. Stage 3 (Candidate)
At this stage, the proposal is considered complete
No further work is possible without implementation experience
Only changes considered critical based on implementation
experience
29 / 48
30. Classes right now
Classes were added in ES6
class Counter {
constructor() {
this.min = 0;
this.max = 100;
this._count = 0;
}
get count() {
return this._count;
}
increment() {
this._count++;
}
decrement() {
this._count--;
}
}
Counter.someStaticProp = 'Static';
30 / 48
31. As a User
const counter = new Counter();
console.log(counter.count); // 0
counter._count = 42;
console.log(counter.count); // 42
31 / 48
34. As a User
const counter = new Counter();
console.log(counter.#count);
// SyntaxError
counter.#count = 42;
// SyntaxError
counter.count = 42;
// Tries to assign to the public field
Private class fields supported in Chrome 74, Node 12
34 / 48
35. Property access in JavaScript
// TypeError prone
const streetName = user.address.streetName;
// Pleasure to read
let streetName = user &&
user.address &&
user.address.streetName;
// Even better, ternaries
const streetName = user ? (
user.address ?
user.address.streetName : undefined
) : undefined;
35 / 48
36. Say ?. (Stage 3)
Enter optional chaining.
Optional chaining operator: ?.
Short circuits if encounters a nullish value.
Available as a Babel plugin, TypeScript 3.7
const streetName = user?.address?.streetName;
const street = user?.getAddress()?.streetName;
36 / 48
37. Assigning default values
const donut = incomingDonut ? incomingDonut : defaultDonut;
// alternative
const donut = incomingDonut || defaultDonut;
// except if this is a number, catch the zero's
// Or a boolean?!
const num = incomingNum == null ? defaultNum : incomingNum;
37 / 48
38. Nullish Coalescing Operator
const num = incomingNum ?? defaultNum;
Checks if a value is nullish.
In Kotlin, this is called the Elvis operator.
Available as a Babel plugin, TypeScript 3.7
38 / 48
39. Bringing it all together 💯
Soon, we could be writing code like this!
const streetName = user?.address?.streetName ?? 'No Street.';
39 / 48
40. Stage 4 (Finished)
Spec editor has signed off.
Ready to be included in the spec.
Test262 acceptance tests have been merged.
Two spec compliant implementations exist.
40 / 48
41. Numbers in JavaScript
Number can only represent values up to 253 - 1
const max = Number.MAX_SAFE_INTEGER;
// 9_007_199_254_740_991
max + 1;
// 9_007_199_254_740_992 ✅
max + 2;
// 9_007_199_254_740_992 ❌
(max + 1) === (max + 2);
// true 🤯
41 / 48
42. BigInt 🎉
A new primitive
Arbitrary precision integers
Works as expected with arithmetic operators
Does not work with Math functions
Chrome, Firefox, Node 12+
BigInt(Number.MAX_SAFE_INTEGER);
// 9_007_199_254_740_991n
BigInt(Number.MAX_SAFE_INTEGER) + 2n;
// 9_007_199_254_740_993n ✅
typeof 100;
// 'number'
typeof 100n;
// 'bigint'
100n + 100;
// TypeError
42 / 48
43. Promise.allSettled
Promise.all added in 2015
Promise.all short-circuits when one of the promises fails
Promise.allSettled returns a promise that resolves when each of
the promises has either been fulfilled or rejected.
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) =>
setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
const results = await Promise.allSettled(promises);
results.forEach(result => console.log(result.status));
// expected output:
// "fulfilled"
// "rejected"
43 / 48
44. globalThis
So many JavaScript environments and all the related global
objects.
// A naive attempt at getting the global `this`. Don’t use this!
const getGlobalThis = () => {
if (typeof globalThis !== 'undefined') return globalThis;
if (typeof self !== 'undefined') return self;
if (typeof window !== 'undefined') return window;
if (typeof global !== 'undefined') return global;
// Note: this might still return the wrong result!
if (typeof this !== 'undefined') return this;
throw new Error('Unable to locate global `this`');
};
const theGlobalThis = getGlobalThis();
Now we just have globalThis, yay portability!
Unified mechanism to access the global this in any
environment.
44 / 48
45. Recap ESNext
ECMAScript is evolved by the TC39 committee
A new version is released every year
Proposals can change till they reach Stage 4
Stage 3 proposals-
Class enhancements
Optional chaining
Nullish Coalescing
Stage 4 proposals-
BigInt
Promise.allSettled
globalThis
45 / 48
46. Conclusion
JavaScript has come a long way since its inception in 1995.
We are a passionate, diverse and vocal community.
As a member of this community, you can participate in its
evolution!
Always bet on JavaScript! 🚀
46 / 48