In this article I’ll show you 15 excellent tips to master the JavaScript language. We'll learn coding...
In this article I’ll show you 15 excellent tips to master the JavaScript language. We'll learn coding shortcuts, features that few people know and some "tricks" that can be very useful for JS programmers in general.
Warning:Not all tips will please everyone. The intention is to show interesting possibilities, but knowing when is the best time to use each of them is up to the programmer (taking into account code readability, for example).
Today’s tips increase in difficulty, so if you find some tip too easy, keep reading and it will get harder (or not, you may already master what I'll teach today ????).
One of the things that we soon learn in JavaScript is that not everything is what it seems to be and that there are many ways that a variable can cause you problems in a dynamic language like this. A very common test that can be done is to check if a variable is null or undefined, or even "empty", as the example below:
let username;
if (name !== null || name !== undefined || name !== '') {
userName = name;
} else {
userName = "";
A simpler way to do the same evaluation would be:
let userName = name || "";
If you don't believe it, please test it out!
So you have to create an Array object and then populate it with its elements, right? Your code will probably look something like this:
let a = new Array();
a[0] = "s1";
a[1] = "s2";
a[2] = "s3";
How about doing the same thing in just one line?
let a = ["s1", "s2", "s3"]
Pretty nice, huh!
Warning: I know this tip's simpler but bare with me, it may help some folks starting from other programming languages
The famous "one-line if/else", the ternary operator is already an old acquaintance for many programmers of C-like languages like Java and C#. It exists in JS as well and can easily transform blocks of code like this:
let big;
if (x > 10) {
big = true;
}
else {
big = false;
}
In this:
let big = x > 10 ? true : false;
Or even simpler:
let big = x > 10;
But does it work with function calls as well? If I have two different functions and I want to call one in case the if is true and one in case the if is false, typically you would do something like this:
function x() { console.log('x') };
function y() { console.log('y') };
let z = 3;
if (z == 3) {
x();
} else {
y();
}
But, hold on to your chair…you can do the same function call using ternary:
function x() { console.log('x') };
function y() { console.log('y') };
let z = 3;
(z==3 ? x : y)(); // Shortcut
Also worth an honorable mention are the ifs that test whether a variable is true, where some programmers still do it that way:
if (likeJs === true)
When they can just do it like this:
if (likeJs)
Yes, even the declaration of variables has its quirks. Although this is not exactly a secret, you still see a lot of programmers making declarations like this:
let x;
let y;
let z = 3;
When they could do this:
let x, y, z = 3;
Regular Expressions are a great tool to create elegant and powerful code when it comes to textual analysis and validation, and data extraction in the case of some types of web crawlers.
You can learn more on how to use regular expressions in these links:
So you want to select just one character from a string, at a specific position, right? I bet the first thing that comes to your mind is to use the charAt function, like below:
"string".charAt(0);
But get this, you get the same result by remembering that analogy of the String being an array of chars:
"string"[0]; // Returns 's'
This is just a leaner notation for Base-10 exponential numbers or the famousnumbers full of zeros. For those of you who are close to mathematics, you won’t be too surprised to see one of these, but a number 10,000 can easily be replaced in JS by 1e4, that is, 1 followed by 4 zeros, as below:
for (let i = 0; i < 1e4; i++) {
This semantic feature is unique to ECMAScript version 6 or higher and greatly simplifies reading string concatenations in variable sets. For example, the concatenation below:
const question = “My number is “ + number + “, ok?”
This one is simple, and you have probably done worse concatenations. As of ES6, we can do this concatenation using template literals:
const question = `My number is $, ok?`
Arrow Functions are shortened ways to declare functions. Yes, more ways to do the same thing that have worked since the first version of JavaScript. For example, below is a sum function:
function sum(n1,n2){
return n1 + n2;
}
We can also declare this function like this:
const sum = function(n1,n2){
return n1+n2;
}
But using arrow functions:
const sum = (n1,n2) => n1 + n2;
This tip is for those functions that are full of parameters and you decided to replace all of them with one object. Or for those functions that really require a configuration object as parameter.
So far no problem, after all who has never experienced this? The problem is having to keep accessing the object that was passed by parameter followed by each property we want to read, right? Like this:
function init(config){
const s = config.s;
const t = config.t;
return s + t;// or config.s + config.t
}
init();
The argument destructuring feature serves precisely to simplify this and at the same time help code readability by replacing the previous statement with this one:
function init(){
return s + t;
}
init();
And to top it off, we can still add default values in properties of our parameter object:
function init(){
return s + t;
}
init();
This way, the value of s will be 1, but the value of t will default to this property, which will be 20.
A very addictive feature is the abbreviated way of assigning properties to objects. Imagine you have a person object that has a name property that is going to be assigned via a name variable. It would look like this:
const name = "Joseph"
const person = { name: name }
// { name: "Joseph" }
While you can do it like this:
const name = "Joseph"
const person = { name }
// { name: "Joseph" }
That is, if your variable has the same name as the property, you don’t need to call it, just pass the variable. The same is true for multiple properties:
const name = "Joseph"
const canCode = true
const person = { name, canCode }
// { name: "Joseph", canCode: true }
Consider the following array of objects:
const animals = [
{
"name": "cat",
"size": "small",
"weight": 5
},
{
"name": "dog",
"size": "small",
"weight": 10
},
{
"name": "lion",
"size": "medium",
"weight": 150
},
{
"name": "elefante",
"size": "large",
"weight": 5000
}
]
Now imagine that we want to take just the names of the animals to add to another array. Normally we would do this:
let animalNames = [];
for (let i = 0; i < animals.length; i++) {
animalNames.push(animals[i].name);
}
But with Map, we can do this:
let animalNames = animais.map((animal) => {
return animal.nome;
})
Note that map expects a function by parameter with at most three arguments:
The first is thecurrent object(as in a foreach)
The second is theindexof the current iteration
The third is theentire array
Obviously this function will be called once for each object in the animal array.
What if we want to iterate through the same array of animal objects as in the previous tip, but this time returning only those whose size is “small”?
How would we do that with regular JS?
let smallAnimals = [];
for (let i = 0; i < animals.length; i ++) {
if (animals[i].size === "small") {
smallAnimals.push(animals[i])
}
}
However, using thefilteroperator, we can do this in a much less verbose and clearer way:
let smallAnimals = animais.filter((animal) => {
return animal.size === "small"
})
Filter expects a function by parameter with the argument that is the object of the current iteration (as in a foreach) and it should return a boolean indicating whether this object will be part of the return array or not (true indicates that it passed the test and will be part of it).
Another important feature of Javascript it thereduce. It allows us to do grouping and calculations on top of collections in a very easy and powerful way. For example, if we wanted to add up the weight of all the animals in our array of animal objects, how would we do it?
let totalWeight = 0;
for (let i = 0; i < animals.length; i++) {
totalWeight += animals[i].weight;
}
But with reduce we can do this instead:
let totalWeight = animals.reduce((total, animal) => {
return total += animal.weight;
}, 0)
Reduce expects a function by parameter with the following arguments:
The first is the current value of theaccumulatorvariable (at the end of all iterations, it will contain the final value)
The second argument is theobject of the current iteration
The third argument is theindexof the current iteration
The fourth argument is thearray with all objects that will be iterated
This function will be executed once on each object in the array, returning the aggregated value at the end of its execution.