Categories
JavaScript Best Practices

JavaScript Best Practices — Generators and Rest/Spread Spacing

Spread the love

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at preventing the use of useless generators and the spacing rest and spread operations.

Always Add yield Statements to Generator Functions

The whole point of generator functions is that it returns a series of values sequentially when the generator is called to create a generator that returns those values.

To return the values, we’ve to use the yield keyword to return the items.

If we’re just returning items without using the yield statement, then we can just use a regular function to do that.

For instance, the following shouldn’t be a generator function:

function* foo() {
  return 1;
}

The because to get the return value from it, we’ve to write the following:

const {
  value: val
} = foo().next();

In the code above, we called the foo generator to return a generator, then we’ve to call next to get the return value.

The object returned has the value , which is the return value 1 and the done property, which is true since all it does is return the value in the generator function.

As we can see, this is a very roundabout way to return something when we can just return the value directly with a regular function.

We can just write:

const foo = () => 1;

to create a regular function that returns 1.

Therefore, if we’re going to define a generator function, we should make sure that we’re returning a series of values with the yield keyword.

For instance, we can write the following code to do that:

function* foo() {
  yield 1;
  yield 2;
}

With the yield keyword we return the value and pause the generator. Then when we call next to invoke it again, we resume the generator and return the next value.

Then we can create a generator by calling foo and loop through the values as follows:

for (const f of foo()) {
  console.log(f);
}

Spacing Between Rest and Spread Operators and Their Expressions

The rest and spread operator are both denoted by ... . While they’re denoted by the same symbol, they’re used differently.

The rest operator is used to get the arguments into an array from the arguments that are called that haven’t been assigned to a value of a parameter.

It’s also used to get the array entries that haven’t been destructured into their own variable into an array.

If the rest operator is used to destructure objects, then the object entries that haven’t been destructured are stored in the variable that’s applied with the rest operator.

The spread operator is used to make shallow copies of arrays and objects and also merge a multiple of them together.

Also, the spread operator can be used to spread an array into an argument when it’s used on an argument of a function.

They both come before the operand. Usually, we don’t have any spaces between the operator and the operand when the operator is the rest or spread operator.

For instance, we usually write something like the following:

const a = {
  foo: 1
};
const b = {
  bar: 2
};
const c = {
  baz: 3
};
const merged = {
  ...a,
  ...b,
  ...c
};

As we can see from the code above, we don’t have any space between the spread operator and a . Likewise, we have the same spacing as objects b and c .

With arrays, we have the same spacing, so we write something like the following:

const a = [1, 2];
const b = [3, 4, 5];
const merged = [...a, ...b];

In the code above, we also don’t have any spaces between the spread operator and a . It’s also the same with b .

If we use the spread operator when calling a function with an array of arguments, we write:

const add = (a, b) => a + b;
const sum = add(...[1, 2, 3]);

We also didn’t add any spacing between the operator and the operand. Also, we didn’t any spaces anywhere else within the parentheses.

However, if we use it with other arguments, then we need some spacing between the argument. We write the following, for example:

const add = (a, b) => a + b;
const sum = add(1, ...[2, 3]);

In the code above, we have a space character after the comma and before the spread operator.

Likewise, with the rest operator, we write the following. If we’re using it on a function, then we write:

const add = (...args) => args.reduce((a, b) => a + b, 0);

We don’t have any spaces inside the parentheses. This is consistent with the previous example where we used the spread operator.

If we have other parameters before the rest parameter, then we need some spacing. For instance, we can define a function as follows:

const add = (a, ...args) => a + args.reduce((a, b) => a + b, 0);

As we can see, we have a space character after the comma.

With destructuring, we write something like the following:

const [a, ...b] = [1, 2, 3];
const {
  c,
  ...rest
} = {
  c: 1,
  d: 2,
  e: 3
}

The spacing is consistent with the other examples, except with object destructuring, where we put each variable on their own line for clarity.

Conclusion

The yield statement should be in JavaScript generator functions to pause and resume the returned generator. Otherwise, we should just define a regular function.

The spacing of the rest and spread operator relative to other entities is standard with one space between some arguments or variables. If there are no other arguments or variables, then no space is required.

There’s definitely no space between the rest and spread operator and its operand.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *