In this post I will review some nice JavaScript tricks that I've lately found when reading the Modern JavaScript course. I have been using JavaScript for several years, but still, I have found some JavaScript capabilities that I was not aware of.
In general I'm less interested in advanced JavaScript syntax/internals which is not relevant for a well written code. For example:
console.log('2' + 1) // prints 21
console.log('' || false) //prints false
console.log('' || "yes") //prints yes
console.log('' ?? "yes") //prints empty line
It is nice to know when you look at these statements why do they act the way they do, but when writing a well clean code, one should avoid such a confusing behavior.
In the next sections, I will review the JavaScript items that are more relevant in my opinion.
BigInt
JavaScript numbers support numbers in range -(253-1) up to (253-1).
But, JavaScript has a built-in support for big integers, for example:
const big1 = 1234567890123456789012345678901234567890n
const big2 = 1234567890123456789012345678901234567890n
console.log(big1 + big2)
Debugger
console.log('Hello')
debugger // break here
console.log('World')
Simple User Interaction
We all use the alert function to print some debug information, but what about getting input from the user? Turns out that we have built-in functions for that:
const name = window.prompt('Your name?', 'John')
const ok = window.confirm(`Hello ${name}, click OK to continue`)
alert(ok ? 'here we go' : 'quitting')
The prompt function opens a text box with an OK and a Cancel buttons.
The confirm function opens a message with an OK and a Cancel buttons.
We will not use this in a production environment, but it is great for debugging purposes.
Nullish Coalescing
When we want to assign a value to a variable only if the value is defined, we can use the nullish coalescing operator. Unlike the OR (||) operator, it will assign the value only if the value is defined.
console.log(null || undefined || false || 'true') // prints true
console.log(null ?? undefined ?? false ?? 'true') // prints false
Optional Chaining
This is a great solution for nested object properties, when you are not sure of the existence of a property. The optional chaining prevents if-conditions to check if the property exists to avoid the "cannot read property X of undefined".
const user1 = {
name: {
first: 'John',
},
}
const user2 = {}
console.log(user1?.name?.first)
console.log(user2?.name?.first)
Object Conversion
You can control the return value upon conversion of an object to a string and to a number.
function User(name, balance = 20) {
return {
name,
balance,
toString: function () {
return `user ${name}`
},
valueOf: function () {
return balance
},
}
}
const u1 = User('John')
console.log(u1) // prints { name: "John", balance: 20}
console.log('hello ' + u1) // prints hello user John
console.log(100 - u1) // prints 80
forEach method
The forEach method can get not only the array elements, but also the array index, and the array itself.
const colors = ['red', 'blue', 'green']
colors.forEach((color, index, array) => {
console.log(color, index, array)
})
Smart Function Parameters
function f({firstName, midName = 'Van', lastName}) {
console.log(firstName, midName, lastName)
}
f({firstName: 'John', lastName: 'Smith'})
Sealing a Property
Javascript enables us to protect an object property. This is done by configuration of the property descriptor.
const obj = {}
Object.defineProperty(obj, "secret", {
value: "You cannot delete or change me",
writable: false,
configurable: false,
enumerable: false,
})
console.log(obj.secret)
delete obj['secret'] // ERROR: Cannot delete property 'secret'
obj.secret = "new value" // ERROR: Cannot assign to read only property 'secret' of object
Object.defineProperty(obj, 'secret', {configurable: true}) // ERROR: cannot redefine property
Some more sealing abilities are listed here.
Final Note
I've wrote this post mostly for myself, but it might be relevant for other senior JavaScript engineers who are, like myself, unaware of these nice JavaScript capabilities.