12 JavaScript tricks that most tutorials don't cover

12 JavaScript tricks that most tutorials don't cover

When I started learning JavaScript, the first thing I did was make a list of tricks that helped me save time. I spied them on other programmers, on different sites and in manuals.

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

We remind you: for all readers of "Habr" - a discount of 10 rubles when enrolling in any Skillbox course using the "Habr" promotional code.

Skillbox recommends: Practical course "Mobile Developer PRO".

Filtering Unique Values

ARRAYS

The Set object type was introduced in ES6, along 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, much more code is needed to perform the same operation.

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

Cache array length in cycles

CYCLES

When you learn for 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 rechecks the length of the array on each iteration.

This can sometimes be useful, but in most cases it's more efficient to cache the length of the array, which will require one access to it. We can do this by defining a variable length where to set the i variable like so:

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

In principle, almost the same as above, but with an increase in the size of the loop, we will get significant time savings.

Short Circuit Rating (McCarthy Rating)

CONDITIONAL OPERATORS

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

x > 100? "more 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 complicated than required. Instead, we can use 'and' && and 'or' || logical operators to evaluate some expressions in an even more concise way. It is often referred to as "short circuit" or "short circuit evaluation".

How it works

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

Using && will return the first false value. If each operand evaluates to true, then the last expression evaluated 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 to false, then 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 don't know its type.

In this case, you can use if/else to check that foo is the right type, but this method can be too long. Therefore, it is better to take our "short circuit".

return (foo || []).length;

If the variable foo has a suitable length, then it will be returned. Otherwise, we will get 0.

Example 2

Have you had problems accessing a nested object? You may not know if an object or one of its subproperties exists, and this can lead to problems.

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

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

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

A better 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' operator && this.state.data will return this.state.data whether it is undefined or not.

Optional chain

One might suggest using optional chaining when trying to return a property deep into the tree structure. So, the question mark symbol? can be used to retrieve a property only if it is non-null.

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

Or, if it matters whether state is defined or not, we could return this.state?.data.

Convert to Boolean

TYPE CONVERSION

Besides the normal boolean true and false functions, JavaScript also treats all other values ​​as truthy or false.

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

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

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

Convert to string

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"

Convert to integer

TYPE CONVERSION

We perform the reverse transformation as follows.

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

This method can also be used to convert the boolean data type 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 an addition operator. To avoid this, use tildes: ~~. This operator is equivalent to the -n-1 expression. For example, ~15 is equal to -16.

Using two tildes in a row nullifies the operation, because - (- - n - 1) - 1 = n + 1 - 1 = n. In other words, ~-16 is equal to 15.

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

<Quick Powers

OPERATIONS

Since ES7, you can use the exponentiation operator ** as a shorthand for exponents. This is much faster than using Math.pow(2, 3). It seems simple, but this moment is included in the list of tricks, since it is far from being mentioned everywhere.

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

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

Prior to ES7, the abbreviation ** could only be applied to base-2 exponents using the bitwise left shift operator <<:

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

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

Float to integer

OPERATIONS / TYPE CONVERSION

If you need to convert a float to an integer, you can use Math.floor(), Math.ceil(), or Math.round(). But there is a faster way, for this we use |, 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 sure of what you are doing.

n | 0 removes everything after the decimal separator, truncating the float to an integer.

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

Removing trailing numbers

The OR operator can be used to remove any number of digits from a number. This means we don't need to typecast like this:

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

Instead, we simply write:

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

Automatic linking

CLASSES

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

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

Trimming an array

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 override its length property like this:

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 is another method, and faster. If speed is what matters to you, here are our picks:

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]

Printing 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]

JSON code formatting

JSON

You may have already used JSON.stringify. Did 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 rendered JSON, and a space value.

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

That's all, I hope that all these tricks were useful. What tricks do you know? Write them in the comments.

Skillbox recommends:

Source: habr.com

Add a comment