Categories
JavaScript Tips

Useful JavaScript Tips — Objects, Undefined, and Month Names

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Nullish Coalescing

The bullish coalescing operator is better for returning default values than the || operator.

|| returns the right expression if the left expression is falsy.

?? only returns the right expression if the left expression is null or undefined .

Therefore, instead of writing:

const favoriteColor = color || 'green';

We write:

const favoriteColor = color ?? 'green';

It’s going to be available in ES2020, which should be released any minute.

Replace Whitespace Inside a String

We can replace whitespace inside a string with the replace method and some simple regex.

To make the replacement, we write:

const str = 'hello world ';
const noSpace = str.replace(/s/g, '')

Then we get that str ‘s whitespaces are removed since s stands for whitespaces.

The new string with the spaces removed is returned, then we can assign it to something else.

Optional Chaining

We can use the optional chaining operator to allow us to navigate nested object properties safely.

For instance, instead of writing:

const color = dog && dog.color && dog.color.name;

to check if each nested property is defined.

We can just write:

const color = dog?.color?.name

The ?. will check if the nested property is defined automatically return undefined automatically if any nested property in the chain isn’t defined.

It’s available in ES2020, and browser support is being added for it.

Dynamic Imports

We don’t have to import modules statically.

There’s the import function to let us import modules dynamically.

We can write:

const module = await import('module');

to import a module with the import function, which returns a promise.

This is why we have the await keyword before the calling import .

With support for top-level await coming, we can have this line on its own.

To do a default import, we can write:

const module = (await import('module')).default()

Calling the default method will resolve to the default export.

Iterate Over Object Properties

We can iterate over object properties in various ways.

We can use the for-in loop to loop over object properties.

For instance, we can write:

for (const key in obj) {
  console.log(key)
}

This will loop over both non-inherited and inherited properties of obj .

The Object.entries method returns the key-value pairs of an object as an array.

It returns the non-inherited properties.

For instance, we can write:

Object.entries(items).forEach(item => {
  console.log(item)
})

or:

for (const item of Object.entries(items)) {
  console.log(item)
}

Both of them will loop through the key-value pairs.

Wait for Multiple Promises to Resolve

If we have 2 or more unrelated promises that we want to wait to resolve, then we use Promise.all to do that.

For instance, we can write:

const data = await Promise.all([promise1, promise2])

Assuming that promise1 and promise2 aren’t dependent on each other, we can get the resolved data of each in an array.

data has an array of resolved values of all the promises.

Get the Month Name of a JavaScript Date

We can get the month name of a JavaScript date by writing:

const date = new Date(2020, 0, 1);
const monthName = date.toLocaleString('default', { month: 'long' });

The toLocaleString method returns the month name for us.

Therefore, monthName is 'January' .

'long' means we return the long name.

Get the Last Element of an Array

We can get the last element of an array with the index arr.length — 1 where arr is an array.

For instance, we can write:

const arr = ['red', 'blue', 'green'];
const last = arr[arr.length - 1];

Then last would be 'green' .

Conclusion

We can use the nullish coalescing operator to return the default value.

The optional chaining operator can be used for safe navigation.

Also, we can get month names, object entries, and the last item of the array easily.

We can do dynamic imports with the import function. It imports modules asynchronously.

If we have multiple independent promises, we should use Promise.all to run them in parallel.

Categories
JavaScript Tips

Useful JavaScript Tips — Formatting Numbers and Objects

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Intl.NumberFormat

We can use the Intl.NumberFormat constructor to format numbers.

For instance, we can write:

const formatter = new Intl.NumberFormat('fr-ca', {
  style: 'currency',
  currency: 'CAD'
})
const price = formatter.format(100);

Then price is “100,00 $” since we set the locale to Canadian French and the currency is Canadian dollars.

We can also set the minimumFractionDigits property to set the minimum number of fractional digits in the return number string.

For instance, we can write:

const formatter = new Intl.NumberFormat('fr-ca', {
  style: 'currency',
  currency: 'CAD',
  `minimumFractionDigits: 2
`})
const price = formatter.format(100);

We set the minimumFractionDigits to 2 so that we’ll always show those digits.

Intl.PluralRules

The Intl.PluralRules constructor lets us return the name of the plural rule to use.

For instance, we can write:

const pr = new Intl.PluralRules('en-gb', {
  type: 'ordinal'
})

Then we can use the select method on pr as follows:

pr.select(0)

Then we get 'other' . If we write pr.select(1) we get 'one' .

pr.select(2) returns 'two' and pr.select(3) returns 'few' .

Now, we can create an object to get the proper ordinal suffix for the language.

For instance, we can write:

const suffixes = {
  'one': 'st',
  'two': 'nd',
  'few': 'rd',
  'other': 'th'
}

So we can format a number by writing:

const format = number => `${number}${suffixes[pr.select(number)]}`

Then we can call the format function with the proper number by writing:

format(0)

Then we get '0th' . format(1) returns '1st' and so on.

Objects

There are many ways to create objects, we can create an object literal, use the Object constructor or use Object.create .

For instance, we can write:

const dog = {};

or:

const dog = Object();

or:

const dog = Object.create();

Object.create is used to create an object with its own prototype.

Object literal is the preferred way if we don’t need to set our own prototype.

We can also create a constructor function to create multiple objects of the same type.

For instance, we can write:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName= lastName;
}

Then we can use the new operator by running:

const person = new Person('james', 'smith');

Objects are always passed by reference.

If we assign it to a variable, then the variable references the original object.

Built-in Object Properties

Most objects have built-in properties.

It has a prototype that has the Object.prototype object, which most objects inherit from.

All objects that aren’t created with a null prototype inherits from Object.prototype .

Object valueOf() Method

JavaScript objects have the valueOf method to return the primitive representation of an object.

For instance, we can write:

const person = { name: 'joe' };
const val = person.valueOf();

Then we get back the object.

However, the value of it is that we can override the method to return what we want.

Object toString() Method

The toString method returns a string representation of an object.

For example, we can write:

const person = { name: 'joe' };
const val = person.valueOf();

Then we get ‘[object Object]' , but we can override it to give us the string value we want.

Check if an Object is Enumerable

The enumerability of an object indicates whether we can traverse an object property.

For instance, we can write:

const person = { name: 'james' }

Object.defineProperty(person, 'age', {
  value: 27,
  enumerable: false
})

Then we can use the propertyIsEnumerable method to check if the property can be traversed.

For instance, we can write:

person.propertyIsEnumerable('name')

and returns true .

And:

person.propertyIsEnumerable('age')

returns false .

So if we use a for-in loop to loop through person , then we’ll see name but not age .

Conclusion

We can create objects with object literals, the Object constructor, and the Object.create method.

To check if an object property is enumerable, then we can use the propertyIsEnumerable method.

There are also methods to format numbers in a language-sensitive manner.

Categories
JavaScript Tips

Useful JavaScript Tips — Timestamps, Combining Values, and Calling Functions

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Extracting UNIX Timestamps in JavaScript

We can get the UNIX timestamp of a Date instance with the + operator.

For instance, we can write:

+new Date(2020, 0, 1)

Then we get 1577865600000.

Also, we can use the getTime method to do the same thing:

new Date(2020, 0, 1).getTime()

Then we get the same thing returned.

The date can also be parsed if it’s in YYYY-MM-DD format.

So we can write:

new Date('2020-01-01').getTime()

And we also get the same thing.

The timestamp is in the number milliseconds since January 1, 1970 12AM UTC.

So we can divide the returned number by 1000 to convert it to seconds.

Combining Array Values into One

We can use the reduce method to reduce array entries into one result.

For instance, if we have:

const cart = [{price: 10}, {price: 40}, {price: 20}];

Then we get can the total price from the cart by writing:

`const reducer = (total, item) => total + item.price;const total =` cart`.reduce(reducer, 0);`

Then total is 70 since we combined all the cart entries’ price properties by adding their values together.

Detect if a Document is Ready

We can detect if a page is loaded completely with the document.readyState property.

For instance, we can write:

if (document.readyState === 'complete') {
  //...
}

to detect if a page is fully loaded and then do something.

We can also check the state periodically using:

let stateCheck = setInterval(() => {
  if (document.readyState === 'complete') {
    clearInterval(stateCheck);
    // document ready
  }
}, 100);

Then we can check the loading state of the page every 100 milliseconds until it’s ready.

In the if block, we call clearInterval to end the timer so we’ll stop checking for the readyState .

Also, we can listen to the readystatechange event with:

document.onreadystatechange = () => {
  if (document.readyState === 'complete') {
    // document ready
  }
}

This is better than creating a timer and running it until the ready state changes.

Calculate the Maximum or Minimum Value of an Array

We can pass in as many values into the Math.max or Math.min methods to check for the max or min values of the array.

For instance, we can write:

const max = Math.max(1, 2, 3);

to return the maximum value or:

const min = Math.min(1, 2, 3);

to return the minimum value.

To pass in an array, we can use the spread operator:

const max = Math.max(...[1, 2, 3]);

or:

const min = Math.min(...[1, 2, 3]);

Or we can use apply as follows:

const max = Math.max.apply(undefined, [1, 2, 3]);

or:

const min = Math.min.apply(undefined, [1, 2, 3]);

apply takes the value of this as the first argument, which is undefined since Math.max and Math.min are static methods.

The 2nd argument is an array of arguments that we want to pass in as arguments into the array.

Destructuring in Function Parameters

We can destructure object parameters with the destructuring syntax.

For instance, we can write:

const greet = ({ name, lastName }) => {
  console.log(`hi, ${name} ${lastName}`);
};

We get the object’s name and lastName properties with the destructuring assignments.

Then we can call it by calling:

greet({ name: 'jane', lastName: 'doe' })

We can also set a default value for the destructured variables.

For instance, we can write:

const greet = ({ name = 'jane', lastName = 'smith' }) => {
  console.log(`hi, ${name} ${lastName}`);
};

Then when we call it by writing:

greet({})

Then name is 'jane' and lastName is 'smith' since we didn’t set the value of either property.

Prevent Changing Built-in Prototypes

We can call Object.freeze to prevent changing objects, which include built-in prototypes.

So we can write:

Object.freeze(Object.prototype);
Object.freeze(Array.prototype);
Object.freeze(Function.prototype);

to prevent changing any built-in prototypes.

Conclusion

We can prevent changing built-in prototypes with Object.freeze .

Also, we can use the spread operator or apply to call a function with an array of arguments.

There are also various ways to get a UNIX timestamp.

Categories
JavaScript Tips

Useful JavaScript Tips — Objects, Methods, and URLs

Like any kind of apps, JavaScript apps also have to be written well.

Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Select a Method Dynamically

We can select a method dynamically by using the bracket notation.

For example, we can write:

animal[isDog ? 'bark' : 'speak']()

instead of:

if (isDog) {
  animal.bark()
} else {
  animal.speak()
}

They do the same thing.

The first uses the ternary operator.

The second us the if statement.

The first one is shorter, so we can consider using it.

Tools for Debugging

We can use the console object to help us debug.

For instance, we can use console.log to log the value of an expression.

We can write:

console.log(a)

to log the value of a .

Chrome Dev Tools

The output of the console log ends up in the Console tab of the Chrome dev tools.

Debugger

The Chrome Dev Tools window also has a debugger built-in.

We can add breakpoints and check the variable values there.

The debugger is in the Sources tab.

We can go to a file and toggle on breakpoints.

Then the code will pause at the breakpoint.

There is more than one type of breakpoint.

One is the XHR/fetch breakpoint which halts the program when a network request is sent.

DOM breakpoints are triggered when DOM element changes.

Event listener breakpoints are trigger when an event happens.

All variables in the scope are printed when a breakpoint is reached.

We can click the + button on the breakpoint to show the values of the expression.

If we want to continue running the code, we can step over the code to resume execution until the next line and stops.

Step into goes into the function being run.

The same pane has the call stack, which has all the functions called recorded.

We can use:

node --inspect

to debug Node.js apps in the browser.

Call and Apply

call and apply can be used to change the value of this and call a function.

It works with traditional function.

For instance, given the following function:

function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}

We can write:

greet.call({
  name: 'james'
}, 'hi');

We used the call function to call greet by setting the value of this with the first argument.

Then pass in the argument we want to the greet function as the second argument.

Therefore, we see that 'hi, james’ is logged in the console.

apply is similar, except the arguments are passed in as an array.

For instance, we can write:

function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}

greet.apply({
  name: 'james'
}, ['hi']);

We have an array instead of just the argument as the 2nd argument.

And we get the same result.

Count the Number of Properties in an Object

We can use Object.keys to return an array of noninherited string property keys.

Therefore, we can use the length property to get the number of properties in the object.

For instance, if we have:

const dog = {
  color: 'white',
  breed: 'poodle'
}

Then we can write:

Object.keys(dog).length

Then we get 2 since dog has 2 own properties.

Sort an Array of Object by its Property Value

The sort method can be used to sort an array of objects by its property value.

For instance, if we have:

const list = [
  { color: 'red', size: 'm' },
  { color: 'green', size: 's' },
  { color: 'blue', size: 'xl' }
]

Then we can write:

list.sort((a, b) => (a.color > b.color)

Then we sort the entries by the color property alphabetically.

Then we get that list is:

[
  {
    "color": "blue",
    "size": "xl"
  },
  {
    "color": "green",
    "size": "s"
  },
  {
    "color": "red",
    "size": "m"
  }
]

Encode a URL

JavaScript comes with the encodeURI() function to encode the URL.

For instance, if we have:

encodeURI("http://example.com/ hello!/")

Then we get:

"http://example.com/%20hello!/"

returned.

There’s also the encodeURIComponent() function that encodes everything including the URL path separators.

For instance, we can write:

encodeURIComponent("http://example.com/ hello!/")

Then we get:

"http%3A%2F%2Fexample.com%2F%20hello!%2F"

returned.

Conclusion

We can select a method dynamically with brackets and expressions inside them.

Also, we can encode URLs with encodeURI or encodeURIComponent depending on our needs.

Debugging is also easy with the debugger.

Sorting items is easy if we pass in a callback.

Categories
JavaScript Tips

Useful JavaScript Tips — Objects

Like any kind of apps, JavaScript apps also have to be written well. Otherwise, we run into all kinds of issues later on.

In this article, we’ll look at some tips we should follow to write JavaScript code faster and better.

Picking and Reject Object Properties

We can use the Object.keys method to get the keys and pick the ones we want.

For instance, we can write:

const reject = (obj, keys) => {
  return Object.keys(obj)
    .filter(k => !keys.includes(k))
    .map(k => Object.assign({}, {[k]: obj[k]}))
    .reduce((res, o) => Object.assign(res, o), {});
}

In the code above, we called Object.keys to get the keys.

Then we called map to map the object key to their own object with the property value of the key as the value.

Then we used reduce to combine the objects array from map into one object with reduce .

We can call it by writing:

const obj = {
  foo: 1,
  bar: 2,
  bar: 3
}
const newOb = reject(obj, ['foo', 'bar']);

Using Object.is for Object Comparisons

We can use the Object.is method for comparisons. The difference between === and Object.is is that NaN equals itself.

For instance, we can write:

Object.is(NaN, NaN);

and it would return true .

Create a Function to Log Values

We can create a function that logs the value and return it so that we can do both when debugging.

For instance, we can write:

const tap = (x) => {
  console.log(x);
  return x;
}

Then we log x and return it with the function.

It’s handy for things like:

.filter(c => tap(c.numItems > 100))

Then we can log the value of the express and return it at the same time.

Array Tricks

We can do a few things with arrays that we may not have thought of yet.

Iterating Through an Empty Array

We can create an arrays with empty slots with the array constructor.

To do that we can write:

const arr = new Array(10);

Passing in a number as its only arguments makes the constructor return array with the given number of empty slots.

Since we passed in 10, we get an array with 10 empty slots.

Populating Empty Arrays

We can use fill to populate empty arrays.

For instance, we can write:

const arr = new Array(10);
const nums = arr.fill().map((_, i) => i)

to create an array with numbers from 0 to 9.

We call fill to fill the empty slots with undefined . Then we can call map with a callback to return the array index to fill it with numbers.

Passing an Empty Parameter to a Method

We can pass in null or undefined to skip arguments.

For instance, we can write:

foo('a', null, 'b')

or:

foo('a', undefined, 'b')

But we can also use the spread operator and write:

foo(...['a', , 'b']);

Then we can skip an entry in the array.

When we spread the entries as arguments, it’ll become undefined so we do the sam,e thing as the previous example.

Unique Array Values

We can remove duplicates from an array by converting it to a set and then convert it back to an array with the spread operator.

For instance, we can write:

const arr = [...new Set([1, 2, 3, 3])];

Then we get:

[1, 2, 3]

as the value of arr .

Binding Objects to Functions

We can use bind to return a function with the value of this that we want.

for instance, if we have:

const getName = function () {
 console.log(this.name);
};

Then if we write:

const getJoe = getName.bind({ name: 'joe' });

Then this.name would be 'joe' in getJoe since bind returns a function that has the value of this as given in the first argument.

Likewise, we can write:

const getJane = getName.bind({ name: 'jane' });

Then this.name would be 'jane' .

Conclusion

We can create arrays with empty slots with the Array constructor.

Then, we can use the fill method to fill it with entries.

We can return a new object without some properties by using Object.keys and Object.assign .

Also, we can use Object.is to compare values including NaN . Therefore, it’s slightly more useful than === .