DEV Community 👩‍💻👨‍💻

DEV Community 👩‍💻👨‍💻 is a community of 966,155 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for JavaScript best practices for writing clean code. Work with Object
Alex Shulaev
Alex Shulaev

Posted on • Updated on

JavaScript best practices for writing clean code. Work with Object

Accepting style guides or coding conventions helps make your code cleaner and more predictable.

The more detailed you describe the rules for your project, the easier it will be for another developer to write code according to your vision.

Now there is a large selection of ready-made style guides from various companies and developers posted in open source. In this article I want to give my advice on adding rules for working with Objects. You can consider this as recommendations, or you can configure ESLint to automatically check these rules.

Object creation

Use literal syntax to create objects. This is a shorter analog of Object constructor.

// bad
const product = new Object();

// good
const product = {};

ESLint rule: no-new-object

How to add to your config:

"rules": {
  "no-new-object": "error"
}

Object shorthand

Use shorthand for property value and methods. This recording option is intuitive and a shorter counterpart.

// bad
const product = {
  name: name,
  id: id,
  getPrice: function () {},
  generateSpecialOffer: function* () {},
};

// good
const product = {
  name,
  id,
  getPrice() {},
  *generateSpecialOffer() {},
};

ESLint rule: object-shorthand

How to add to your config:

"object-shorthand": [
  "error",
  "always",
  {
    "ignoreConstructors": false,
    "avoidQuotes": true
  }
]

Quotes

Property names of objects can be written with or without quotes, both of these options are valid. By analogy with the previous rules, we can decide not to use quotes as this is a shorter record, but in fact, it is not quite so, the fact is that we have cases when the presence of quotes is mandatory. For example, when a property name has space or dash. However, this is not so common, so using quotes for all properties will be irrational. The best option is to use quotes only when it is necessary.

// bad
const product = {
  "description": "",
  "short-description": "",
};

// good
const product = {
  description: "",
  "short-description": "",
};

ESLint rule: quote-props

How to add to your config:

"quote-props": ["error", "as-needed", { "unnecessary": true }]

Object.prototypes

The Object.create() method creates a new object, using an existing object as the prototype of the newly created object. This allows you to override methods (e.g. hasOwnProperty), which can break the logic of the application. To solve this problem, you need to always call methods from Object.prototype

// bad
const product = {
  name: "name-1",
  id: 1,
};

console.log(product.hasOwnProperty("name")); // true?

// good
const product = {
  name: "name-1",
  id: 1,
};

console.log(Object.prototype.hasOwnProperty.call(product, "name")); // true

ESLint rule: no-prototype-builtins

How to add to your config:

"no-prototype-builtins": "error"

The "extends": "eslint:recommended" property in a configuration file enables this rule.

Destructuring

Destructuring is now very popular and indeed it has proven itself in a much more convenient way than accessing a property through expression. The main advantage of destructuring is a shorter code entry. You no longer need to create additional variables to store properties

const product = {
  name: "name-1",
  id: 1,
  price: "100$",
};

// bad
const getPrice = (product) => {
  const price = product.price;
  return `Full price: ${price}`;
};

// good
const getPrice = ({ price }) => `Full price: ${price}`;

ESLint rule: prefer-destructuring

How to add to your config:

"prefer-destructuring": [
  "error",
  {
    "VariableDeclarator": {
      "array": false,
      "object": true
    },
    "AssignmentExpression": {
      "array": true,
      "object": false
    }
  },
  {
    "enforceForRenamedProperties": false
  }
]

Object spread

If you have a task to combine several objects or get a copy of objects, you need to use Object.assign with special care (or even better, use Spread syntax instead). Let's look at a simple example right away

// bad
const product = {
  name: "name-1",
  id: 1,
};
const copyProduct = Object.assign(product, { name: "name-2", id: 2 });

console.log("copyProduct", copyProduct); // {name: "name-2", id: 2}
console.log("product", product); // {name: "name-2", id: 2}

As a result, we got a mutation of the first object. This is not a bug, everything works as it should if you read about Object.assign(), but the problem is that it creates situations where the developer can forget about this behavior and get an unexpected result. To get the expected result without mutations you need to do

// still not very good
const product = {
  name: "name-1",
  id: 1,
};
const copyProduct = Object.assign({}, product, { name: "name-2", id: 2 });

console.log("copyProduct", copyProduct); // {name: "name-2", id: 2}
console.log("product", product); // {name: "name-1", id: 1}

Here we solved the problem with the mutation, but this structure is very wordy. We have a better option

// good
const product = {
  name: "name-1",
  id: 1,
};
const copyProduct = { ...product, name: "name-2", id: 2 };

console.log("copyProduct", copyProduct); // {name: "name-2", id: 2}
console.log("product", product); // {name: "name-1", id: 1}

With spread syntax, we were able to get rid of an unexpected mutation and the solution became much more concise.


Thank you for reading! This was a spontaneous article, now I'm writing a series of articles about the development of a side project, take a look if you are interested in it. See you soon 👋

Top comments (3)

Collapse
 
kubasovp profile image
Peter Kubasov

Hi!
Example of destructurization
The object is not passed on to a good example :)

Collapse
 
alexandrshy profile image
Alex Shulaev Author • Edited on

Hi Peter!
I'm glad to receive from you my first comment on dev.to 🥳 😄
Unfortunately, I'm not sure that I correctly understood your remark, could you clarify a little more. Do you mean that I didn't call the getPrice method with the product object to make the destructuring work?

Collapse
 
kubasovp profile image
Peter Kubasov

Hi Alex!
Thank you! It was my first comment on dev.to, too :)
Sorry for the late reply, I was busy learning English :)
At first I thought that the code wasn’t working and that there was something missing. So I needed some time to figure out that you need to recall the method with the given object using getPrice(product);

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

⭐️🎀 JavaScript Visualized: Promises & Async/Await

async await