Let's find out how to keep your sugar balanced, shall we?
First, let's have a quick look at the definition of syntactic sugar 🤓
Syntactic sugar is a syntax aimed to express the same code command in different and mostly better ways, in the same language.
For example:
Array.prototype.filter
is an alternative to forEach
loop for filtering out an array according to a specific condition, andi++
instead of i = i + 1
for
is an alternative to while
for the same purpose.So is it JUST syntactic sugar? No. In fact, syntactic sugar is more like ***A**lternative**G****ood* syntax that is meant to empower your code with ***S****implicity*, ***U****sability,* and make your code more ***R****eadable*.
Or as I like to remember it, the SUGAR rule.
Yup, the following code
//Before syntactic sugar
const result = [];
for (let i = 0; i < data.length; i++) {
const x = data[i];
if (x % 2 === 0) {
result.push(x);
}
}
can easily be replaced by the syntactic sugar filter
, with a proper refactor and 💥
//After
const isEven = (number) => number % 2 === 0;
const result = data.filter(isEven);
Shorter, more concise and easier to read.
If you use syntactic sugar correctly, you can absolutely avoid silly but annoying JavaScript “weird” traps (as expected for being so magical 😆), _such as the Deadpool BaNaNa trap — causing by having to type too many _+
to compute string from other strings and variables — like below:
With the magic of string template:
const banana = `ba${fillme}a`;
Usability at its best. 😉
Such as code writing efficiency, and performance relatively. As we all know, [[]](https://medium.com/front-end-weekly/es6-set-vs-array-what-and-when-efc055655e1a)
is a better performance choice compared to [new Array()](https://medium.com/front-end-weekly/es6-set-vs-array-what-and-when-efc055655e1a)
. Similarly with [{}](https://medium.com/front-end-weekly/es6-map-vs-object-what-and-when-b80621932373)
instead of [new Object()](https://medium.com/front-end-weekly/es6-map-vs-object-what-and-when-b80621932373)
or even [Object.create()](https://medium.com/front-end-weekly/es6-map-vs-object-what-and-when-b80621932373)
.
However, note that in general, performance efficiency *really***differs****per use case**.
And that's when SUGAR flashes the 🚨warning sign.
Everything has a limit before it becomes unbearable. No exception. Too much salt will cost you your blood pressure. Too much protein will cause indigestion. But you do need them, within a right amount.
Same goes to syntactic sugar. It's sweet, easy to use, hence we developers are tempted to switch to it whenever we can (who wouldn't love easy solution?) — sometimes without even considering possible negative effects. Because as long as it is within KISS, it's good.
Is it? No, absolutely not.
Let's look at the following code: Only 2–3 lines of code, concise and short.
However, is it easy to get straight away what this block of code does? For some of you who are familiar with the problem, which the above code is trying to solve, it's not too hard to figure out.
(it's for flattening an array, in case you are curious).
But for first timer, it's challenging.
Readable? Not really.
...
operator is another example.
Lovely, but also hard to interpret sometime, due to the fact that it can be **spread** operator or **rest** parameter is quite confusing for many developers, especially when both are presented in the same context as above.
*Remember, your code needs to be **clear** and **straightforward** before everything else, for the sake of the next developer. *Hence, **without**readability, your beloved syntax **is no longer syntactic SUGAR.**
While less code does mean lighter JS file, it doesn't necessarily make the performance better, such as:
This function, theoretically — *without** considering inner loop *combinations.map()
— takes O(n). Linear time - should be good, right? But that's just in theory.
Why? Because:
map
loops through the original array, ***creates***new array based on it and *returns* the new array — **new resource** is allocated. Same goes to filter
, reverse
, etc...reduce
also requires to loop through the new array again, and returns a reduced value based on that array with a calculation formula passed.for
loop, regardless how optimised the JS profiler is built.map
and reduce
here will only make the matter worse, not better (browser **needs** to “freeze” for the first *map*
to complete, and then **again** for *reduce*
to complete, and so on).for
loop is not in a need of syntactic sugar that badly. We can rewrite the above code using for
and stills maintain KISS rule with efficiency (both in resource allocation and performance)
Apparently the syntactic version is way slower than the classic [for](http://bit.ly/map-reduce-for-benchmark)
as in a performance test, despite of the same time efficiency (O(n²)).
In short, it's O(n) but NOT always O(n), so be careful. Sometimes it's better to use the classic for
loop. Period.
Exactly, not all syntactic sugar is supported in every browser. That's why we need Babel — for instance — to make it works.
Yup. Remember our little friend IE (or even Safari 9+?). Some of ES6 syntactic sugar like ...
and for..of
will not be supported, and suddenly your following sweet and clean code which originally looked like this
const sumUp = (...numbers) => {
let sum = 0;
for (const number of numbers) {
sum += number;
}
return sum;
};
After going through Babel's compiler, will become (sort of):
var sumUp = function sumUp() {
for (
var _len = arguments.length, numbers = Array(_len), _key = 0;
_key < _len;
_key++
) {
numbers[_key] = arguments[_key];
}
var sum = 0;
for (
var _iterator = numbers,
_isArray = Array.isArray(_iterator),
_i = 0,
_iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();
;
) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var number = _ref;
sum += number;
}
return sum;
};
And it suddenly becomes not that efficient anymore 😅
As long as your users still use certain browsers, your code needs to work well on them. Thus before putting a new syntactic sugar in your code, **don't forget to double check or read the instructions** (aka the documentation).
*Being extra careful with new syntax is always a good habit *😉.
In general, syntactic SUGAR is good (and totally recommended) to use, as long as it is accompanied with CARE, which is:
To sum it up, code responsibly — think of efficiency, maintainability, readability for other developers 🤞. As long as you know your sugar limit, your syntactic sugar will be sweet 🍬 and there will not be any risk of diabetes 🚀.
Disclaimer: _This article is based on my talk on the same subject in CityJS Conf 2019 last May. _A recorded version is available on Youtube*. Enjoy and happy coding everyone! *😸
If you'd like to catch up with me sometimes, follow me on Twitter | Facebook or simply visit my portfolio website.