Categories
JavaScript Tips

Useful JavaScript Tips — Object Properties and Copying

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.

Comparing 2 Objects with Object.is()

An alternative way to compare 2 objects is with the Object.is method.

It’s almost the same as the === operator.

However, NaN is the same as itself.

For instance, we can write:

Object.is(a, b)

Then we can compare 2 variables a and b .

Get the Prototype of an Object

We can get the prototype of an object with the Object.getPrototypeOf method.

For instance, we can get the prototype of an object as follows:

const animal = {
  name: 'james',
  age: 7
};

const dog = Object.create(animal);

We created a dog object with Object.create so that dog will inherit from animal .

So if we call Object.gerPrototypeOf with it:

const prot = Object.getPrototypeOf(dog);

Then:

prot === animal

would be true since animal is dog ‘s prototype.

Get the Non-inherited Symbols of an Object

The Object.getOwnPropertySymbols returns all the non-inherited symbol keys of an object.

If we have the follow object:

const name = Symbol('name')
const age = Symbol('age')
const dog = {
  [name]: 'james',
  [age]: 7
}

Then we can call getOwnPropertySymbols as follows:

const syms = Object.getOwnPropertySymbols(dog);

Then we get that syms is :

[Symbol(name), Symbol(age)]

Get Non-inherited String Keys of an Object

The Object.getOwnPropetyNames method lets us get an array of string keys of an object.

The keys return aren’t inherited from any prototypes.

For instance, we can write:

const dog = {
  breed: 'poodle'
}

const keys = Object.getOwnPropertyNames(dog);

Then we get [“breed”] as the value of keys .

Get Key-Value Pairs of an Object

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

For example, we can write:

const person = { name: 'james', age: 18 }
const pairs = Object.entries(person);

Then pairs would be:

[
  [
    "name",
    "james"
  ],
  [
    "age",
    18
  ]
]

where the first entry of the inner arrays is the key name, and the 2nd is the value.

Add a Single Property to an Object

We can call Object.defineProperty on an object to create a new property.

For instance, we can write:

const dog = {};
Object.defineProperty(dog, 'breed', {
  value: 'poodle'
})

We added the breed property into dog using the defineProperty method.

Add Multiple Properties to an Object at Once

In addition to the Object.defineProperty , there’s also the Object.defineProperties method to add multiple properties to an object.

For instance, we can write:

const dog = {};
Object.defineProperty(dog, {
  breed: {
    value: 'poodle'
  },
  name: {
    value: 'james'
  },
})

Then dog would be {breed: “poodle”, name: “james”} .

It’s a convenient way to add multiple properties to an object at once.

Creating an Object with Object.create

Object.create lets us create an object with a prototype.

For instance, we can write:

const animal = {
  name: 'james',
  age: 7
};

const dog = Object.create(animal);

Then dog is has animal as its prototype.

It’ll inherit all the properties from animal .

So dog.name would be 'james' .

Copying and Combining Objects with Object.assign

Object.assign lets us combine multiple objects into one or copy them.

To make a copy of an object, we can write:

const copy = Object.assign({}, original)

We make a copy of the original object and assigned it to the copy variable.

{} should be the first argument so that we won’t modify any existing objects and copy them into an empty object.

To combine multiple objects, we can write:

const merged  = Object.assign({}, obj1, obj2)

We copy all the own string properties from obj1 and obj2 into the empty object in the first argument.

So merged would have all the own properties from both.

Conclusion

We can compare and copy objects with static Object methods.

Also, we can define properties on an object with them.

Also, we can copy and merge objects with the Object.assign method.

It does a shallow copy so that the top-level is copied.

Categories
JavaScript Tips

Useful JavaScript Tips — Closures and Arrays

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.

Looping Over Arrays

JavaScript provides many array methods that we can use to work with arrays in a concise manner.

while Loop

We can use the while loop to loop through arrays.

For instance, we can write:

let index = 0;
const arr = [1,2,3];

while (index < arr.length) {
  console.log(arr[index]);
  index++;
}

We update the index at each iterator to access the objects in arr .

Classical for Loop

There’s also the classical for loop for iterating overt items in an array.

It works by setting up the initial condition, the ending condition, and the array index update statement on the first line of the loo.

For instance, we write:

const arr = [1,2,3];
for (let index = 0; index < arr.length; index++) {
  console.log(arr[index]);
}

forEach

We can use the forEach method to loop through array entries.

It takes a callback that we can run code on each entry.

For instance, we can write:

const arr = [1,2,3];

arr.forEach((val, index, array) => {
  console.log(index, array, val);
});

We have arr which we called forEach on.

Then we get the array entry with val , the index of the entry with index , and the array itself with array .

map

map lets us map our array entries from one to the other.

For instance, we can write:

const arr = [1,2,3];
const cube = x => x ** 3;
const cubes = arr.map(cube);

We have the cube function which we pass in as the callback for the map function.

x has the array entry’s value.

cubes has the new array with each entry of arr cubed.

reduce

The reduce method lets is combine the entries into a single value.

For instance, we can write:

const arr = [1,2,3];
const sum = (total, y) => total + y;
const sum = arr.reduce(sum, 0);

We have arr which we called reduce on by passing in the sum function as its callback.

The first parameter is the accumulate total so far and the second is the entry being added into the total .

The 2nd argument of reduce is the initial value.

The combination of the entries is done from left to right.

There’s also a reduceRight method that combines entries from right to left.

filter

The filter method returns an array that meets the condition in the callback.

For instance, we can write:

const arr = [1,2,3];
const isEven = x => x % 2 === 0;
const evenArr = arr.filter(isEven);

We have isEven , which is a function that checks if an array entry x is evenly divisible by 2.

We call filter on arr with isEven passed in.

Then evenArr should have all the even entries in arr .

every

The every method checks if every entry in the array meet some given condition.

For instance, we can write:

const arr = [1,2,3];
const under10 = x => x < 10;
const allUnder10 = arr.every(under10);

We have under10 , which checks if every entry is under 10.

x is the array entry.

Then we called every with under10 as the callback.

allUnder10 should be true since all entries in arr are less than 10.

some

some checks if one or more elements in the array match the given condition.

For instance, we can write:

const arr = [1,2,3];
const under10 = x => x < 10;
const someUnder10 = arr.some(under10);

Then someUnder10 should be true since there’s at least one entry in arr that’s less than 10.

Closures

We can create an enclosed scope in loops by running:

for (let i = 0; i < 3; i++) {
  funcs[i] = ((value) => {
    console.log(value);
  })(i);
}

This way, we get the value of the index variable looped when we called the function in funcs .

Conclusion

We can use array methods to save us the effort of looping through entries and doing what we want.

Also, we should wrap our code in IIFEs to create a closure with the index variable value of a loop.

Categories
JavaScript Tips

Useful JavaScript Tips — Objects and Scopes

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.

Polluting Global Scope

We should never define global variables to declare the global scope.

To avoid this, we use let and const to declare variables.

For instance, we write:

ler x = 1;

or:

const y = 2;

We shouldn’t declare variables with var or without a keyword before it.

They both declare global variables, which we don’t want.

Likewise, we should not use function declarations.

Instead, we should use function expressions.

So instead of writing:

function foo() {}

We write:

const foo = () => {}

We can also enclose our variables within IIFEs to keep them private:

(() => {
  let  = 1;
})()

Now they are not accessible outside the function.

Use Strict Mode

We should use strict mode to disallow some bad constructs in our code.

For instance, we can’t assign things to reserved keywords like:

undefined = 1;

Also, we can’t accidentally define global variables by assigning to variables without declaring them.

So we can’t create global variables like:

foo = 1;

foo is a global variable since we declared it without a keyword.

Strict Equality

We shoild use the === or !== operators to compare values since data type conversions aren’t done before comparison with them.

For instance, instead of writing:

a == b

We write:

a === b

It’s much safer than the == operator.

Likewise, for inequality, we should use the !== operator.

So we can write:

a !== b

instead of:

a != b

Use && or || to Conditionally Evaluate Expressions

We should use the || operator to return the right operand if the left operand is falsy.

For instance, we can write:

const str = '' || 'foo';

to return 'foo' since empty string is falsy.

Similarly, we can use the && operator to evaluate the right expression if the left expression is truthy.

So we can write:

const baz = obj.foo && obj.foo.baz;

This way, obj.foo.baz is only returns only if obj.foo is truthy.

This can avoid lots of undefined errors when accessing nested properties.

Convert Value Types

We can convert strings to numbers by using the + operator.

For instance, we can write:

const foo = +'100'

to get 100 as the value of foo .

Also, we can use the !! operators to convert anything to a boolean.

For example, we can write:

!!0

to convert it to false since it’s falsy.

Follow Style Guides

There are many good style guides that we can follow to write good JavaScript code.

For instance, we can following the Google JavaScript Style Guide, airbnb/javascript guide, and others so that we can follow some good practices when writing JavaScript.

To automate the process of checking for bad good, we can use ESLint co check for them.

Creating Immutable Objects in JavaScript

We can create immutable objects in JavaScript with the Object.seal method.

For instance, we can write:

Object.seal(foo);

to make foo immutable.

It makes the object immutable and doesn’t return anything.

It prevents the modification of property descriptors.

There’s also the Object.preventExtensions for preventing adding properties to an object.

For instance, we can write:

Object.`preventExtensions`(foo);

Also, we can write:

`Object.freeze(`foo`);`

Then we can do all the things that seal and prevenExtensions does.

Creating Hash Maps without Side Effects

We can create a pure object without a prototype by using Object.create with the null argument.

For instance, we can write:

const map = Object.create(null);

Then the map object won’t have a prototype.

We can use it as a dictionary safely.

Cloning Immutable Objects

We can use the clone package to clone an object.

For instance, we can write:

const clone = require('clone');

const a = { foo: { bar: 1 } };
const b = clone(a);

Now we can clone a and make the clone a value of b so that we can us manipulate b without affecting a .

Conclusion

We can prevent objects from being modified with some Object methods.

Also, we can use the clone property to clone objects.

In addition, we can use && or || to do things other than creating boolean expressions.

Categories
JavaScript Tips

Useful JavaScript Tips — Numbers and String Whitespaces

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.

Check if a Number is Finite

The isFinite method lets us check if a value is a finite number or not.

For instance:

Number.isFinite(1)

returns true .

On the other hand:

Number.isFinite(1)

returns false .

Format a Decimal Number into a String

We can use the toFixed method to format a decimal number into a string.

For instance, we can write:

(20.22).toFixed()

and get '20' .

Also, we can pass in the number of decimal digits we want to keep by writing:

(20.22).toFixed(1)

and get “20.2” .

Format a Number into a Language Sensitive String

The toLocaleString method lets us get a string that has a number formatted according to the locale.

For instance, we can write:

(20.22).toLocaleString('fr-ca')

Then we get “20,22” .

Format a Number into Exponential Notation

The toExponential method lets us convert a number into a string that’s in exponential notation.

For instance, we can write:

(21.22).toExponential()

Then we get “2.122e+1” .

Change the Number of Decimal Digits of a Number

The toPrecision method formats a number into a string that has the given number of decimal digits.

For instance, we can write:

(21.21).toPrecision(5)

Then we get “21.210” .

We can also pass in a number that’s smaller than the number of decimal digits in the number.

Then we get a string with the number formatted into exponential notation.

For instance, we can write:

(21.21).toPrecision(1)

And we get “2e+1” .

Converting a Number to a String

The toString method converts a number to a string.

The argument it takes is the radix.

For instance, if we want to convert the decimal number 10 to binary, we can write:

(10).toString(2)

Then it returns “1010" .

Parsing a String into an Integer

We can parse a string into an integer with the parseInt method.

For instance, we can write:

Number.parseInt('10.00')

and we get back 10.

It also takes a second argument with the radix.

So if we want to convert it to a given base, we can do that by writing:

Number.parseInt('16', 16)

Then we get 22 since we converted '16' to a base 16 number.

Parsing a String into a Floating Point Number

There’s the Number.parseFloat method to convert a string into a floating-point number.

For instance, we can write:

Number.parseFloat('10.00')

and get 10.

It can also convert a string to a number if it starts with a number by removing the non-numerical parts and converting the rest to a number.

For example, we can write:

Number.parseFloat('36 bottles')

Then we get 36.

Check if a Number is Within a Safe Range

In JavaScript, a number is considered to be safe if it’s between -2 ** 53 and 2 ** 53 .

To check that, we can use the Number.isSafeInteger method.

For instance, we can write:

Number.isSafeInteger(2 ** 53)

which returns true , and:

Number.isSafeInteger(2 ** 53 + 1)

which is false .

Checking if a Value is NaN

Checking for NaN is tricky.

Therefore, we should use the Number.isNaN to do it since we can’t use === to do the comparison.

For instance, we can write:

Number.isNaN(NaN)

and that would return true .

Also:

Number.isNaN('foo' / 'bar')

returns true .

Check if a value is an Integer

The isInteger method lets us check if a value is an integer.

We can use it by writing:

Number.isInteger(1)

which returns true , or:

Number.isInteger(0.2)

which returns false .

Trimming the beginning of a String

We can remove whitespace from the beginning of a string with the trimStart method.

For instance, we can write:

'   foo'.trimStart()

Then it returns “foo” .

Trimming the End of a String

There’s also the trimEnd method to remove whitespace from the end of a string.

For example, we write:

'foo   '.trimStart()

Then it returns “foo” .

Trimming Both Ends of a String

The trim method will remove whitespace from both ends of a string.

For instance, we can write:

'   foo   '.trim()

Then it returns 'foo' .

Conclusion

There are various ways to parse and check numbers.

Also, JavaScript strings have methods to remove whitespaces.

Categories
JavaScript Tips

Useful JavaScript Tips — Loops and Sorting Dates

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.

Break Out of a for Loop

If we want to end a for loop early, we can use the break keyword.

For instance, we can write:

for (const val of list) {
  console.log(val);
  if (val === 'b') {
    break;
  }
}

If val is 'b' then we end the loop with break .

We can also do the same with an old for loop:

for (let i = 0; i < list.length; i++) {
  console.log(list[i]);
  if (list[i] === 'b') {
    break;
  }
}

We do the same thing, except it’s longer because of the indexes.

Check if an Object is Empty

We can check if an object is empty with the Object.entries method. It returns the non-inherited key-value pairs in an object.

Therefore, we can write:

Object.entries(obj).length === 0

to check if obj is empty by checking the array returned by Object.entries ‘s length.

It’s a good idea to check that obj is actually by adding:

obj.constructor === Object

Lodash also has the isEmpty function to do the same thing.

We can write:

_.isEmpty(obj)

to do the check.

Return the Result of an Async Function

An async function returns a promise with the resolved value of the promise.

For instance, if we write:

const getJSON = async () => {
  const response = await fetch('./file.json')
  return response
}

then we return a promise that resolves to the response object. We can then use it with other async functions or call then on it.

Check if a JavaScript Array has a Given Value

We can use the includes method to check if an array has the given value.

For instance, we can write:

['red', 'green'].includes('red');

Then we can check if 'red' is in the array it’s called on. It should return true since it’s included in the array. If the value in the argument isn’t included, then it returns false .

Rename Fields When Object Destructuring

We can rename fields when we’re destructuring objects. To do that, we can use the : symbol to do it.

For instance, we can write:

const person = {
  firstName: 'james',
  lastName: 'smith'
}

const { firstName: name, lastName } = person;

Then we renamed firstName to name. So name is 'james'.

Using Symbols

We can use symbols to create an identifier that’s always unique. Each symbol that’s created won’t be the same even if they have the same content.

For instance:

Symbol() === Symbol()

returns false .

Symbol('foo') === Symbol('foo')

is also false .

We can use them as property identifiers.

For instance, we can write:

const foo = Symbol('foo');
const obj = {
  [foo](){
    //...
  }
}

We can also write:

const foo = Symbol('foo');
class Bar {
  [foo](){
    //...
  }
}

We can use symbols in both objects and classes as identifiers.

Public Class Fields

We can add public class fields by putting them in constructors or methods.

For instance, we can write:

class Foo {
  constructor() {
    this.count = 0
  }
}

Sorting an Array by Date

To sort an array by date, we can use the sort method and compute the difference between the dates 2 entries and return it.

For instance, given the following array:

const tasks = [{
    title: 'eat',
    date: new Date('2020-06-23')
  },
  {
    title: 'drink',
    date: new Date('2020-06-10')
  },
  {
    title: 'sleep',
    date: new Date('2020-06-22')
  }
]

We can sort it by date descending order by writing:

tasks.sort((a, b) => +b.date - +a.date);

sort sorts an array in place.

The + operator converts dates to UNIX timestamps so that we can compute their difference.

If the difference is more than 1, then sort reverses the order of the 2 entries.

So we get:

[
  {
    "title": "eat",
    "date": "2020-06-23T00:00:00.000Z"
  },
  {
    "title": "sleep",
    "date": "2020-06-22T00:00:00.000Z"
  },
  {
    "title": "drink",
    "date": "2020-06-10T00:00:00.000Z"
  }
]

as the value of tasks .

We can flip a and b around to sort tasks in date ascending order.

To make a copy of tasks before sorting, we can use the spread operator or slice as follows:

const sortedTasks = [...tasks];
sortedTasks.sort((a, b) => +b.date - +a.date);

or:

const sortedTasks = tasks.slice();
sortedTasks.sort((a, b) => +b.date - +a.date);

Conclusion

We can use break to end a loop early.

To sort objects with dates, we can return the difference between the timestamps.

Also, we can check if an object is empty with Object.entries to return an array of key-value pairs and use the length property.