Javascript — Object creation

Sergio Daniel Cortez Chavez
9 min readDec 8, 2021
Photo by Quino Al on Unsplash

Javascript is a widely used language, in which there has not always been an obvious way to create objects. During this post, we will navigate over a variety of ways to create objects, we will see which of them have been part of the evolution of the language, and we will see a bit of how Javascript managed to simulate the concept of classes through its prototyping system.

Introduction

In short, an object is a set of key/value pairs that allow aggregate values and functions under one name/variable.

Is important to know that in Javascript almost any value is an Object, the only exceptions are:

  • Strings. A sequence of characters, where each element is considered to be a single UTF-16 code unit.
  • Numbers. Is a primitive data type used for positive or negative integer, float, binary, octal, hexadecimal, and exponential values.
  • Symbols. An immutable value that was introduced in ECMAScript 2015 that are often used to identify unique objects properties.
  • true/false. Define a boolean value.
  • null. Define an intentional absence of the value.
  • undefined. Define the absence of value, but this value is only defined by the compiler.

As mentioned earlier, an object is a set of key-pair values, where each key can be a String or a Symbol and the value can be anything like a function, number, string, or even another object.

For the next few minutes, I going to explain the many options that Javascript gives us for defining Objects, and what is the effect of each one.

Literal Object

The first and more basic way to create a one-time object is through literal objects. To define a Literal Object you need to define a set o key:value pairs that are separated by a comma and are wrapped in curly braces.

Example:

const john = {
name: 'John',
age: 12,
address: 'Steve Michael #23, ...',
sayHello: function() {
console.log('hello');
},
}

Each key:value pair is going to define a property on the new object, where the key is the name, and the value is the content. On this example, john defines four properties (name, age, address, sayHello).

Note. Methods are functions stored as object properties.

Symbols

Is important to remember that the value that defines the name of the property, can be a String or a Symbol. In this case, when you only define a String without quotes, this is taken as String, but is possible to create objects that use a Symbol, for example:

const name = Symbol();const john = {
name: 'John'
}
console.log(name); // Output: John

To define a Symbol, you need to call Symbol . Is possible to add a String argument like Symbol('name') but this is only used for debugging purposes. The important concept to remember is that each Symbol that you generate are unique, even when the same value is passed as a parameter:

Symbol() == Symbol() // Output: false
Symbol('name') == Symbol('name') // Outpu: false

This special type was added to Javascript to make it possible to add new properties without breaking existing code, for example. Imagine that the Javascript standard adds a new property like .toString() but for XML, in this case, the method is named .toXML() , but what about with the existed code that was created before and that defines a custom method with the same name?.

For these cases Javascript make available a new global variable named toXML , that, in reality, is a Symbol. This new global variable gives access to the new method without breaking the old code that defines a property with the same name.

Shortcut with literal objects.

Another important tip is that when you are creating a literal object from an existed variable and the name of the property is going to be the same as the variable, you can pass the variable only, instead of the key/value pair. The object is going to create a property with the same name of the variable, and the same value.

Example:

const name = 'John';
const age = 12;
const address = 'Steve Michael #23, ...';
const sayHello = function() {
console.log('hello');
}

const john = {
name,
age,
address,
sayHello
};

Note. One good habit that you can use when defining literal objects is to add a command after the last property of the objects. In the case of adding an extra property, you only care for appending a new key-value pair without worrying about adding a comma before.

Use cases

You can use a Literal Object when you need a fast way to group a set of related values. This way of creating objects is not ideal if you need to create the same type of object from many parts of your code.

Object.create

A more manual and difficult way to use is the Object.create function.

Object.create(proto[, propertiesObject])

Where:

  • proto. Is a prototype object.
  • propertiesObject. Is an optional parameter or an object with properties that are going to be aggregated to the new object.

But what is a prototype?

A prototype is a special object that is associated with one or many objects in Javascript. In special, Javascript has a root prototype named Object that are related to almost all objects.

If you print Object.Prototype you are going to see some familiar methods:

{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}constructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()__proto__: (...)get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()

Some of the information printed is irrelevant for this article, but you can look for familiar methods like toString() and if you remember, many of the objects that you use in Javascript has this method. However this method isn't defined by you, instead, this is defined by the Object.prototype that is the root prototype that is linked with almost all objects in javascript.

So, if you intend to access some of the properties on an object, you can find two situations.

  1. The property is defined directly in the object. You can check this with the hasOwnProperty method.
  2. The property is defined on some of the prototypes objects that are related to the object, so the property is accessed through a mechanism named prototype chain.

Note. You can access the nearest prototype through the __proto__ property of some object, for example instance.__proto__ . This is the direct prototype, but the prototypes object can have another prototype, this is known as prototype chain.

In this post, I don't go to delve into the prototype area but is important to have general knowledge. For more information about prototypes and the prototype chain, check this excellent post.

From the explanation of the prototypes, is possible to define new objects through the Object.create function, for example:

const empty = Object.create(Object.prototype);

This is the same that:

const empty = {};

In the same way, you can define a more complex object, like this one:

const john = Object.create(Object.prototype, {name: 'John', age: 21});

This is the same that:

const john = {name: 'John', age: 21};

Use cases

The method Object.create was introduced in ECMAScript 5.1 to give some shortcut for simulating an inheritance with the prototype system that Javascript support. Right now, there is a friendlier way to achieve a similar result using the reservation words class, extends, etc.

Function constructor

Photo by Rodion Kutsaev on Unsplash

Another form to create an Object is through a Function. You can create objects through a function if you prefix with the new keyword. For example:

function Person(name, age, address) {
this.name = name;
this.age = age;
this.address = address;
}
const john = new Person('John', 12, 'Steve Michael #23, ...');

The thiskeyword makes references to the new instances that are going to be created. In this case, is a good practice to capitalize the name of the function to define that this is a function constructor and not a normal function.

The function constructor allows to create of many instances that share the same structure, for example:

// Person function constructo definition...const john = new Person('John', 12, 'Steve Michael #23, ...');
const mark = new Person('Mark', 23, 'Main Street Marcus #224, ...');

This form allows creating of many instances that share the same form. Is important to mention that Javascript allows defining properties a runtime, in other words, not all the created instances with Person will have the same properties, is possible to add extra properties once the object was created, for example:

// Person function constructo definition...const john = new Person('John', 12, 'Steve Michael #23, ...');
const mark = new Person('Mark', 23, 'Main Street Marcus #224, ...');
mark.pet = 'Flash';

In this case, mark has an extra property that johndoesn't have.

Note. One extra note about the instances created by a function constructor is that each instance has Person.prototype as her prototype, and the Person.prototype has as a prototype the Object.prototype . Each function that you create in Javascript create your own prototype, and this prototype define a special function named constructor, in this case, this function is the same as the one you defined and allows you to initialize the object.

Use cases

The advantage of a function constructor is that it defines a central point to create an instance or object that shares a base shape, in contrast with the literal object that defines the structure each time that intends to create a new object.

ES6 Classes

Javascript ES6 introduces the Class the keyword as a new way for creating objects. This method is like the old constructor function but more similar to the way of creating objects in other languages like C++ and java.

One example is:

class Person {
constructor(name, age, address) {
this.name = name;
this.age = age;
this.address = address;
}

sayHello() {
console.log('hello');
}
}
const john = new Person('John', 12, 'Steve Michael #23, ...');

The behavior is the same, only change the form of define and initialize the class. In this case, the constructor is a special method that is called in an implicit way when you create a new instance of the class.

Use cases

The use cases for this form of creating objects are similar to the function constructor but add a more friendly syntax for achieving inheritance than the previous method Object.create .

Another advantage of this syntax is that make more familiar the process of creating classes from the persons who from languages like C++, Java, etc, and aggregate more keywords like extends , interface , etc for simulating the same concepts of a language based on classes.

Merging Existing Objects

Photo by Markus Spiske on Unsplash

The last methods are the common ways to generate new objects but sometimes is necessary to create a new object from some existing ones. For these cases, you can use Object.assign .

Signature:

Object.assign(target, ...sources)

Where a target is an object where all the properties of the source objects are going to be overridden if exist, or are created if not exist.

This function has some case edges:

  1. The function only copies the properties that are enumerable.
  2. If one property is read-only, is going a raise a TypeError exception and the target object will remain unchanged.

Example:

const target = {};
const john = {
name: 'John',
age: 12,
address: 'Steve Michael #23, ...',
sayHello: function() {
console.log('hello');
},
};
const cloneOfJohn = Object.assign(target, john);

This is an example, but you can add more source objects, like this:

const target = {};
const john = {
name: 'John',
age: 12,
address: 'Steve Michael #23, ...',
sayHello: function() {
console.log('hello');
},
};
const extraInformation = {
genrer: 'male',
email: 'john@em.com'
}
const johnWithExtraInfo = Object.assign(target, john, extraInformation);

One modern way of achieving the same result is with the spread operator.

const john = {
name: 'John',
age: 12,
address: 'Steve Michael #23, ...',
sayHello: function() {
console.log('hello');
},
};
const extraInformation = {
genrer: 'male',
email: 'john@em.com'
}
const johnWithExtraInfo = {...john, ...extraInformation};

Thanks for reading!

This is all for this post, I hope the content has been to your liking, see you in the next post.

--

--