12 JavaScript techniques not found in most tutorials

12 JavaScript techniques not found in most tutorials

When I started learning JavaScript, the first thing I did was make a list of techniques that helped me save time. I picked them up from other programmers, various websites, and manuals.

In this article, I will show 12 great ways to improve and speed up your JavaScript code. In most cases, they are universal.

Reminder: for all readers of 'Habr' - a discount of 10,000 rubles when enrolling in any Skillbox course with the promo code 'Habr'.

Skillbox recommends: Practical Course "Mobile Developer PRO".

Filtering Unique Values

ARRAYS

The Set object type was introduced in ES6. Together with the spread operator, we can use it to create a new array that contains only unique values.

const array = [1, 1, 2, 3, 5, 5, 1]
const uniqueArray = [...new Set(array)];
 
console.log(uniqueArray); // Result: [1, 2, 3, 5]

In a normal situation, achieving the same operation would require much more code.

This technique works for arrays containing primitive types: undefined, null, boolean, string, and number. If you are working with an array containing objects, functions, or additional arrays, you will need a different approach.

Caching Array Length in Loops

LOOPS

When studying for loops, you follow the standard procedure:

for (let i = 0; i < array.length; i++){
  console.log(i);
}

However, with this syntax, the for loop checks the length of the array on each iteration.

Sometimes this can be useful, but in most cases, it's more efficient to cache the array length, which requires only one access to it. We can do this by defining a length variable, where we set variable i, for example, like this:

for (let i = 0, length = array.length; i < length; i++){
  console.log(i);
}

Essentially, it’s almost the same as above, but as the loop increases in size, we will achieve a significant time savings.

Short-Circuit Evaluation (McCarthy Evaluation)

CONDITIONAL OPERATORS

The ternary operator is a quick and efficient way to write simple (and sometimes not-so-simple) conditional statements:

x > 100 ? 'greater than 100' : 'less than 100';
x > 100 ? (x > 200 ? 'greater than 200' : 'between 100-200') : 'less than 100';

But sometimes even the ternary operator is more complex than necessary. Instead, we can use 'and' && and 'or' || logical operators to evaluate some expressions in an even more concise way. It's often referred to as 'short-circuiting' or 'short-circuit evaluation.'

How it works

Let's say we want to return just one of two or more conditions.

Using && will return the first false value. If each operand evaluates as true, the last computed expression will be returned.

let one = 1, two = 2, three = 3;
console.log(one && two && three); // Result: 3

console.log(0 && null); // Result: 0

Using || will return the first true value. If each operand evaluates as false, the last computed value will be returned.

let one = 1, two = 2, three = 3;
console.log(one || two || three); // Result: 1

console.log(0 || null); // Result: null

Example 1

Let's say we want to return the length of a variable but we aren't sure of its type.

In this case, we could use if/else to check that foo is of the appropriate type, but this method can be too lengthy. Therefore, it's better to use our 'short-circuiting'.

return (foo || []).length;

If the variable foo has an appropriate length, it will be returned. Otherwise, we will get 0.

Example 2

Have you had trouble accessing a nested object? You may not know if the object or one of its sub-properties exists, which can lead to issues.

For instance, we wanted to access the property data in this.state, but data is not defined until our program returns the fetch request.

Depending on where we use it, calling this.state.data could prevent the application from running. To solve the issue, we could wrap this in a conditional statement:

if (this.state.data) {
  return this.state.data;
} else {
  return 'Fetching Data';
}

A more suitable option would be to use the 'or' operator.

return (this.state.data || 'Fetching Data');

We cannot change the code above to use &&. The ‘Fetching Data’ && this.state.data will return this.state.data whether it is undefined or not.

Optional chaining

You might consider using optional chaining when trying to return a property deep within a tree structure. The question mark ? can be used to extract a property only if it is not null.

For example, we could refactor the above example to get this.state.data?.. (). That is, data is returned only if the value is not null.

Or, if it's important to know whether state is defined or not, we could return this.state?.data.

Transforming to Boolean

TYPE CONVERSION

In addition to the usual boolean functions true and false, JavaScript also considers all other values as truthy or falsy.

Unless otherwise specified, all values in JavaScript are truthy except for 0, "", null, undefined, NaN, and of course, false. The latter are falsy.

We can easily switch between the two using the ! operator, which also converts the type to a boolean.

const isTrue  = !0;
const isFalse = !1;
const alsoFalse = !!0;
 
console.log(true); // Result: true
console.log(typeof true); // Result: "boolean"

String Conversion

TYPE CONVERSION

A quick conversion of an integer to a string can be done as follows.

const val = 1 + "";
 
console.log(val); // Result: "1"
console.log(typeof val); // Result: "string"

Integer Conversion

TYPE CONVERSION

The reverse conversion is done like this.

let int = "15";
int = +int;
 
console.log(int); // Result: 15
console.log(typeof int); // Result: "number"

This method can also be used to convert boolean data types to regular numeric values, as shown below:

console.log(+true);  // Return: 1
console.log(+false); // Return: 0

There may be situations where + will be interpreted as a concatenation operator rather than addition. To avoid this, it's advisable to use double tildes: ~~. This operator is equivalent to the expression -n-1. For example, ~ 15 equals -16.

Using two tildes nullifies the operation since — (- — n — 1) — 1 = n + 1 — 1 = n. In other words, ~ -16 equals 15.

const int = ~~"15"
console.log(int); // Result: 15
console.log(typeof int); // Result: "number"

<Quick Powers

OPERATIONS

Starting with ES7, you can use the exponentiation operator ** as a shorthand for powers. It's much faster than using Math.pow(2, 3). It seems simple, but this point is included in the list of tricks because it's not mentioned everywhere.

console.log(2 ** 3); // Result: 8

Do not confuse it with the ^ symbol, which is usually used for exponentiation. But in JavaScript, this is the XOR operator.

Before ES7, the ** shortcut could only be applied for powers with a base of 2 using the bitwise left shift operator <<:

Math.pow(2, n);
2 << (n - 1);
2 ** n;

For example, 2 << 3 = 16 is equivalent to the expression 2 ** 4 = 16.

Float to Integer

OPERATIONS / TYPE CONVERSION

When you need to convert float to integer, you can use Math.floor(), Math.ceil(), or Math.round(). But there’s also a faster way using |, that is, the OR operator.

console.log(23.9 | 0);  // Result: 23
console.log(-23.9 | 0); // Result: -23

Behavior largely depends on whether you are dealing with positive or negative numbers, so this method is only suitable if you are confident in what you are doing.

n | 0 removes everything after the decimal point, truncating the floating-point number to an integer.

You can achieve the same rounding effect using ~~. After the forced conversion to an integer, the value remains unchanged.

Removing closing numbers

The OR operator can be used to remove any number of digits from a number. This means we don’t need to convert types, as shown here:

let str = "1553";
Number(str.substring(0, str.length - 1));

Instead, we just write:

console.log(1553 / 10   | 0)  // Result: 155
console.log(1553 / 100  | 0)  // Result: 15
console.log(1553 / 1000 | 0)  // Result: 1

Automatic binding

CLASSES

ES6 arrow functions can be used in class methods, and binding is implied. This allows you to say goodbye to repetitive expressions like this.myMethod = this.myMethod.bind(this)!

import React, { Component } from 'react';
 
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
 
  myMethod = () =&gt; {
    // This method is bound implicitly!
  }
 
  render() {
    return (
      <>
        <div>
          {this.myMethod()}
        </div>
      </>
    )
  }
};

Array trimming

ARRAYS

If you need to remove values from an array, there are faster methods than splice().

For example, if you know the size of the original array, you can redefine its length property as follows:

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array.length = 4;

console.log(array); // Result: [0, 1, 2, 3]

But there’s another method, and it’s faster. If speed matters to you, here’s our choice:

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array = array.slice(0, 4);

console.log(array); // Result: [0, 1, 2, 3]

Outputting the last value(s) of an array

ARRAYS
This technique requires the use of the slice() method.

let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log(array.slice(-1)); // Result: [9]
console.log(array.slice(-2)); // Result: [8, 9]
console.log(array.slice(-3)); // Result: [7, 8, 9]

Formatting JSON code

JSON

You may have already used JSON.stringify. Do you know that it helps format your JSON?

The stringify() method takes two optional parameters: a replacer function that can be used to filter the displayed JSON, and a space value.

console.log(JSON.stringify({ alpha: 'A', beta: 'B' }, null, 't'));

// Result:
// '{
//     "alpha": A,
//     "beta": B
// }'

That's it, I hope all the mentioned techniques were useful. What tricks do you know? Share them in the comments.

Skillbox recommends:

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster