Categories
JavaScript Best Practices

JavaScript Best Practices — Object Creation

Spread the love

JavaScript lets us do a lot of things. It’s sometimes too forgiving in its syntax.

In this article, we’ll look at how to create objects, including namespacing members with global objects, destructuring dependencies, and private members.

Object Creation

We can create JavaScript objects in a few ways.

We can either use object literals or constructor functions/classes.

However, there’re some patterns that are useful for creating objects in an orderly manner.

Namespace Pattern

We can separate JavaScript code into namespaces so that we don’t have so many global variables.

Namespaces let us avoid name collisions and reduce the need to prefix names.

For instance, we can write:

const APP = {};
APP.Foo = class {}
APP.Bar = class {}
APP.c = 1;
//...

The code above creates a global APP object which has multiple classes inside it.

They’re in their own object so that name collision is minimized compared to having them all at the top level.

Now that we have JavaScript modules, we can just use that instead.

But if we’re using old-fashioned scripts, we can use this pattern.

It’s a bit more to type. Also, the state of the object is propagated everywhere since it’s all under one global object.

Nested names also mean longer property resolutions lookups.

General Purpose Namespace Function

We can’t assume the object that we have been in the script.

Therefore, we may want to check if it’s there first before we put things in there.

For instance, we can write:

APP = APP || {};

In case APP isn’t defined yet, we should check with the || operator to see if it’s defined.

We can also create a namespacing function.

For instance, we can write:

const namespace = (path) => {
  const parts = path.split('.');
  const obj = {};
  let nestedObj = obj;
  for (const p of parts) {
    nestedObj[p] = {};
    nestedObj = nestedObj[p];

}
  return obj;
}

const obj = namespace('foo.bar');

The code above created a namespace function that takes an object path separated by dots.

It separates the path and creates the empty nested objects that we need.

Then we can put that in the function.

Declaring Dependencies

Most dependencies are namespaces, which we can use to reference global variables from dependencies easily.

For instance, we can write:

const {
  foo,
  bar
} = APP;

to destructure the APP namespace into its properties.

This way, we can access them individually in functions or any other piece of code.

Private Properties and Methods

JavaScript has no private properties and methods in objects and constructors.

To keep the private, we either keep them in modules or functions.

If we keep them in objects, anything can access them.

For instance, we can write:

const obj = {
  foo: 1,
  getFoo() {
    return this.foo;
  }
};

Then we can access the properties as follows:

obj.foo
obj.getFoo()

Nothing can stop us from accessing them.

Likewise, with constructors and classes, everything is public.

For instance, if we have:

class Foo {
  constructor() {
    this.foo = 1;
  }

  getFoo() {
    return this.foo;
  }
};

Then we can write:

(new Foo()).foo;

or:

(new Foo()).getFoo();

Private Members

If we want private members, then they can’t be a property of this .

So we can write:

class Foo {
  constructor() {
    const foo = 1;
  }

  getFoo() {
    return this.foo;
  }
};

We can only put them into functions and declare them with let and const to avoid exposing them to the public.

With the constructor function syntax, we can write:

function Foo() {
  const foo = 1;
};

Privileged Methods

Public members that have access to private members are called privileged methods.

We can define one as follows:

function Foo() {
  const foo = 1;
  this.getFoo = function() {
    return foo;
  }
};

getFoo is a privileged method as it can access foo .

This way, we can keep things private while being able to use them when needed.

Conclusion

We can use the namespace pattern to put members in a global object to avoid name collisions.

Also, there’re no private members in classes or constructors. So we’ve to define ordinary data with let or const to make them private.

Privileged methods are ones that can access private data.

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 *