3 Ways to Create Object Instances in OOJS
When a programming language is all about objects, the first thing we need to learn is how to create objects. Creating objects in JavaScript is fairly easy: a pair of curly braces will do the job, however, that is neither the only way to create an object nor the only way you’ll ever need to use.
In JavaScript, object instances are created from built-in objects and come to existence when the program is running. For example, Date
is a built-in object that gives us information about dates. If we want to show the current date on a page, we need a runtime instance of Date
that carries the information about the current date.
JavaScript also allows us to define our own objects that can produce their own object instances in runtime. In JavaScript, everything is an object and every object has an ultimate ancestor called Object
. The creation of an object instance is called instantiation.
Read Also: Ultimate Guide to Getters and Setters in JavaScript
1. The new
operator
One of the most common and well-known methods to create a new object instance is by using the new
operator.
You need a constructor to make the new
operator work. A constructor is a method of an object that puts together a new instance of that object. Its basic syntax looks like this:
new constructor()
A constructor can accept arguments that can be used to change or add properties to the object instance it constructs. The constructor has the same name as the object it belongs to.
Here is an example how to create an instance of the Date()
object with the new
keyword:
dt = new Date(2017, 0 , 1) console.log(dt) // Sun Jan 01 2017 00:00:00 GMT+0100
Date()
is the constructor to create a new Date
object. Different constructors for an object take different arguments to create the same kind of object instances with varied attributes.
Not all built-in objects in JavaScript can be instantiated like Date
. There are objects that don’t come with a constructor: Math
, JSON
and Reflect
, but they’re still ordinary objects.
Among the built-in objects that have constructor(s), Symbol
cannot be called in the constructor style to instantiate a new Symbol
instance. It can only be called as a function which returns a new Symbol
value.
Also, among the built-in objects that have constructor(s), not all need their constructors to be called with the new
operator in order to be instantiated. Function
, Array
, Error
, and RegExp
can also be called as functions, without using the new
keyword, and they’ll instantiate and return a new object instance.
2. The Reflect
object
Backend programmers might be already familiar with Reflection APIs. Reflection is a feature of programming languages to inspect and update some of the basic entities, such as objects and classes, at runtime.
In JavaScript, you could already perform some reflection operations using Object
. But, a proper Reflection API eventually came to exist in JavaScript as well.
The Reflect
object has a set of methods to create and update object instances. The Reflect
object doesn’t have a constructor, so it can’t be instantiated with the new
operator, and, just like Math
and JSON
, it can’t be called as a function either.
However, Reflect
has an equivalent of the new
operator: the Reflect.construct()
method.
Reflect.construct(target, argumentsList[, newTarget])
Both the target
and the optional newTarget
arguments are objects having their own constructors, while argumentsList
is a list of arguments to be passed to the constructor of target
.
var dt = Reflect.construct(Date, [2017, 0 , 1]); console.log(dt); // Sun Jan 01 2017 00:00:00 GMT+0100
The code above has the same effect as instantiating Date()
using the new
operator. Although you can still use new
, Reflection is an ECMAScript 6 standard. It also allows you to make use of the newTarget
argument, which is another advantage over the new
operator.
Read Also: ECMAScript 6 – 10 Awesome New Features
The value of newTarget
‘s prototype (to be exact, it’s the prototype of newTarget
‘s constructor) becomes the prototype of the newly created instance.
A prototype is the property of an Object, the value of which is also an object, carrying the properties of the original object. In short, an object gets its members from its prototype.
Here, let’s see an example:
class A { constructor() { this.message = function() { console.log('message from A') } } } class B { constructor() { } message() { console.log('message from B') } data() { console.log('data from B') } } obj = Reflect.construct(A, [], B) console.log(obj.message()); // message from A console.log(obj.data()); // data from B console.log(obj instanceof B) // true
By passing B
as the third argument to Reflect.construct()
, the prototype value of the obj
object is made to be same as the prototype of B
‘s constructor (which has the properties message
and data
).
Thus, obj
can access the message
and data
, available at its prototype. But, since obj
is made using A
, it also has its own message
it received from A
.
Even though obj
is constructed as an array, it is not an instance of Array
, because its prototype is set to Object
.
obj = Reflect.construct(Array, [1,2,3], Object) console.log(obj) // Array [ 1, 2, 3 ] console.log(obj instanceof Array) // false
Reflect.construct()
can be useful when you want to create an object using more than one blueprint.
3. The Object.create()
method
You can also create a new ordinary object with a specific prototype via Object.create()
. This, too, might seem very similar to using the new
operator, but it’s not.
Object.create(O[, propertiesObject])
The O
argument is an object that serves the prototype for the new object that will be created. The optional propertiesObject
argument is a list of properties you might want to add to the new object.
class A { constructor() { } message() { console.log('message from A') } } var obj = Object.create(new A(), { data: { writable: true, configurable: true, value: function(){return 'data from obj'} } }) console.log(obj.message()) // message from A console.log(obj.data()) // data from obj obj1 = Object.create(new A(), { foo: { writable: true, configurable: true, value: function(){return 'foo from obj1'} } }) console.log(obj1.message()) // message from A console.log(obj1.foo()) // foo from obj1
In the obj
object, the added property is data
, while in obj1
, it’s foo
. So, as you see, we can have properties and methods added to a new object.
This is great when you want to create multiple objects of the same kind but with different supplementary properties or methods. The Object.create()
syntax saves the trouble of coding all of them separately.
Read Also: Getting Started with JavaScript Promises