ES2015 tl;dr; - using functions
Ever got tired of how weird functions (and everything else) work weird in JavaScript? Well, get used to it, cuz we got a long way ahead, but stuff’s getting better, and the functions’ improvements are one of the things we can have a toast to.
📸🙅 No more self
-ies
Arrow functions are pretty cool. Aside from less verbosity, they solve a problem that people have been having for quite some time: the this
. No more var self = this;
or bind
everywhere.
function Cook(name, speed) {
this.name = name;
this.speed = speed;
}
Cook.prototype.prepareBatch = function () {
setTimeout(function () {
console.log(this.name + ' finished a batch');
}, this.speed);
}
const cook = new Cook('Walter White', 1000);
cook.prepareBatch();
// logs "undefined finished a batch" after 1 second
By simply changing the function ()
in the setTimeout
to () =>
we’re ensuring the this
has the scope we want:
setTimeout(() => {
console.log(this.name + ' finished a batch');
}, this.speed);
// this time we'll get "Walter White finished a batch"
This is due to lexical binding, which means it gets bound to the scope where it was first defined and not to the actual function usage. Since we added it to Cook
object, then the scope is bound to it’s instance.
Defaults have arrived 🎉
Long has been the time when we needed to check if the argument was indeed passed and if not, assign it something so that tears don’t stream down our faces. ES2015 finally allowed us to use the defaults we so longed for:
function Cook(name, speed = 5000) {
this.name = name;
this.speed = speed;
}
const cook = new Cook('Jesse Pinkman');
console.log(cook);
// logs "Cook { name: 'Jesse Pinkman', speed: 5000 }"
Another example that would trigger errors back in the day given that we pass no params to a function that relies on an array being given:
function addIngredients (ingredientsList = []) {
// this would trigger an error
// since one "cannot read length of undefined"
for (let i = ingredientsList.length - 1; i >= 0; i--) {
console.log('Pour ' + ingredientsList[i]);
}
}
addIngredients(); // Outputs nothing
addIngredients([
'Methylamine',
'Acetic acid',
'Phenyl acetic acid'
]);
// Outputs three times "Pour [ingredient name here]"
Destructuring basics and named parameters
First off, let’s start by presenting the common concept of constructing & extracting:
const cook = {};
cook.name = 'Walter White';
cook.speed = 1000;
// object constructed
let currentCookName = cook.name;
let currentCookSpeed = cook.speed;
// extracting information from object
Now destructuring allows us to extract the information for sources given their structure, therefore giving us real multiple left-hand assignment:
let [mainCook, assistantCook] = ['Walter White', 'Jesse Pinkman'];
console.log(mainCook, assistantCook);
// logs "Walter White Jesse Pinkman"
If you’re using names on your left-hand assignment to map to the source properties, you can get the info you need regardless of the order they appear:
let {speed, name} = cook; // equivalent to `let {speed: speed, name: name}`
console.log(speed, name);
// logs "1000 'Walter White'"
let {speed: currentCookSpeed, name: currentCookName} = cook;
console.log(currentCookSpeed, currentCookName);
// logs "1000 'Walter White'"
Putting it all together to allow your function
to receive named and optional parameters aside from default values:
function printCookDetails({name, speed = 3000} = {}) {
console.log(name + ' cooks one batch every ' + speed/1000 + ' second(s)');
}
printCookDetails({speed: 5000, name: 'Jesse Pinkman'});
//logs "Jesse Pinkman cooks one batch every 5 seconds"
printCookDetails({name: 'Gale Boetticher'});
//logs "Gale Boetticher cooks one batch every 3 seconds"
printCookDetails(cook);
//logs "Walter White cooks one batch every 1 seconds"
Hopefully this will help you out a bit. Next in line is a short post about Rest Parameters and Spread Operators.