Constructing Objects

An overview of the various ways you can create objects in JavaScript.

Scroll down...

Content

Resources

Comments

As we've mentioned, objects are the core foundation of JavaScript. Until now, we've pretty much just used them as a simple data structure that store key-value pairs (where the value can be either a property or a method). But there is so much more we can do with objects.

We've said it before and we'll say it again -- basic objects and functions are the two ingredients that JavaScript uses to accomplish almost everything it does. We've already covered functions so now it's time to dig deeper into how to create objects in the first place.

In JavaScript, there are three main ways to build objects:

  1. Using the literal syntax, e.g. myObj = { ... }
  2. Using the more common "constructor pattern"
  3. Using the newer Object.create syntax

With a good understanding of the this keyword, we can now use functions to construct new objects. This pattern is known as the "Constructor Pattern" and you'll see it used frequently.

The goal of this lesson is for you to absorb this key principle and, particularly, to become comfortable working with constructors.

This is another lesson where it's useful to follow along with the examples!

1. The Literal Syntax

As you've seen before, the most basic way to create objects is to use the "literal" syntax to set them to a variable:

var myObj = {
  foo: "bar",
  fooFunc: function() { console.log("hi"); }
};

This is the most common way you'll work with objects that only need to be used once. The object that is created is an "anonymous object", which you can tell because it is listed as simply an "Object" in the console:

myObj;
// Object {foo: "bar"}
//   foo: "bar"
//   fooFunc: ()
//   __proto__: Object

For most use cases, this is all you need.

2. Constructing Objects with Constructor Functions

Though the literal syntax is fine for creating individual objects, in more object-oriented settings you will want to be able to construct multiple instances of a particular object that all share similar properties and methods. In JavaScript, this is most frequently accomplished by using the "constructor pattern".

In this case, we'll set up an ordinary function in such a way that it can be used to create new object instances and then call it a "constructor function". This is done by adopting these simple conventions:

  1. Capitalize the function name (not necessary, just convention)
  2. Declare the function "constructor style" (not necessary, just convention)
  3. Don't include a return value (not necessary, just convention)
  4. Use the this keyword inside the function to help set properties of our new object. This is where the magic happens!

To show how this works, we'll first refresh how functions can be declared in JavaScript and then step through the process of creating an object using a constructor.

Refresher: Declaring Functions in JavaScript

Because many new JavaScript developers get confused by the fact that there are two effectively identical ways of declaring a function in JavaScript, let's look at them explicitly in the example below.

It's conventional to use the "literal style" to declare most "normal" functions in JavaScript while the "constructor style" is typically reserved for functions which will later be used to construct objects.

// Method 1: Literal style, the most common way
//   to declare a function in JavaScript
var normalFunc = function() {
  return "normalFunc here!"
};


// Method 2: Constructor style, aka "factory style"
// This is typically used when the function will be
//   used to build objects later with the "constructor
//   pattern"
// Constructors don't typically return anything
function futureConstructor() {
  console.log("futureConstructor here!")
};


// In both cases, we now have a function in the
//   global namespace
// In this example, the function simply returns
//   a string with it's name (not too interesting)
//   since we haven't used the `new` keyword to
//   call it.
normalFunc();
//=> "normalFunc here!"
futureConstructor();
// "futureConstructor here!"
//=> undefined

This is nothing special. Now how do we take a normal function and make it construct objects?

Calling Functions as Constructors Using 'New'

Regardless of how you set up your function, the cool part comes when you use that function to be the blueprint for objects by running it with new, e.g:

var myObj = new someConstructor();

This essentially performs the following three steps:

  1. Creates a new blank object to work with
  2. Immediately runs the constructor function on that object (so the new object is now set to this)
  3. Returns the original object (regardless of what your function was supposed to return)

To take advantage of this process, we use this inside of our constructor to set properties of the new object:

// build a simple constructor that sets
//   a few properties
function MyConstructor() {
  this.someProp = "value!";
  this.someMethod = function() { return "I'm a method!"; } ;
}


// Use this as a template for constructing
// a new object
var myObj = new MyConstructor();


// Take `myObj` for a test drive to verify
//   that it has actually acquired all the properties
//   of the constructor
myObj.someProp;
//=> "value!"
myObj.someMethod();
// "I'm a method!"

That's pretty handy -- we now have the ability to create any number of objects that come pre-populated with properties and methods.

In a similar fashion to other object-oriented languages, we typically call myObj an Instance of MyConstructor. The properties that you've attached to the new object are a lot like (and sometimes referred to as) "instance variables". The methods are a lot like "instance methods". MyConstructor is acting an AWFUL lot like a Ruby class...

Anonymous Objects vs Named Object Instances

If you recall from above, creating an object using the literal syntax makes an anonymous object which is identified as simply Object. When we use a constructor, the new object is now identified as an instance of that constructor:

// Anonymous object using literal syntax
var anonObj = {};
//=> Object {}

// Constructed object
var myObj = new MyConstructor();
//=> MyConstructor {someProp: "value!"}

We'll dig deeper into this new "instance" of MyConstructor but first, let's pause and try to build our own constructor.

Understanding Constructors by Faking Our Own

Hopefully, the procedure above gives you a good mental model for how constructors are called. If you're still a bit shaky on exactly what constructors do, you can accomplish the same thing on your own using the call method you just learned about in the previous lesson:

// Create our constructor function
// Note that whereas before our constructor
//   didn't return anything (and, in truth,
//   whatever it returned would be ignored),
//   now we actually return the object itself
function MyConstructor() {
  this.someProp = "value!";
  this.someMethod = function() { return "I'm a method!"; };
  return this; // << this is new
}


// We can now fake what `new` does by running
//   the `MyConstructor` function on a brand
//   new object which is passed into the `call`
//   method you learned about before.
// As you know, `call` simply runs
//   `MyConstructor` and sets `this` to whatever
//   you pass into it, in this case a blank object.
// It should be easy to see how the `MyConstructor`
//   function we defined above then adds properties
//   and methods to this object before returning it.
var myObj = MyConstructor.call({});


// See, same result!
myObj;
// Object {someProp: "value!"}

This should help you see that using the new keyword with a constructor function simply calls that function on a newly created object and then ensures that the object is returned in the end. Nothing too special.

...and now we'll return to our regularly scheduled programming...

Examining an Object's Properties

When you use constructors with new to create a new object, your constructor factory attaches any properties you've set with this directly onto that new object. These properties become defined on that particular object instance and are independent of any other objects.

To illustrate that properties on object instances are independent from one instance to another, here's an example:

// Declare our constructor function
function MyConstructor() {
  this.someProp = "value!";
  this.someMethod = function() { return "I'm a method!" };
}

// Create 2 new objects with the constructor above
var firstObj = new MyConstructor();
var secondObj = new MyConstructor();


// Observe that both got their properties as expected
firstObj;
//=> MyConstructor {someProp: "value!", someMethod: function}
secondObj;
//=> MyConstructor {someProp: "value!", someMethod: function}


// Now override the property on just one of them
firstObj.someProp = "not a value!";


// Verify that it's only overridden that object's prop
firstObj;
//=> MyConstructor {someProp: "not a value!", someMethod: function}
secondObj;
//=> MyConstructor {someProp: "value!", someMethod: function}

Examining an Object's Methods

“Methods” are just functions that are attached to objects. And methods are defined on each individual object instance just like properties are. In fact, properties and methods in JavaScript are almost indistinguishable from each other.

In exactly the same way that we just saw above with properties, modifying a method on one object does not affect the same method on a different object:

// Our constructor
function MyConstructor(){
  this.someProp = "value!";
  this.someMethod = function(){ return "I'm a method!" };
}


// Create 2 new objects with the constructor above
var firstObj = new MyConstructor();
var secondObj = new MyConstructor();


// Observe that both got their methods as expected
firstObj;
//=> MyConstructor {someProp: "value!", someMethod: function}
secondObj;
//=> MyConstructor {someProp: "value!", someMethod: function}


// Now override the method on just one of them
secondObj.someMethod = function(){
  console.log("Different Method!");
}


// Verify that it's only overridden that particular
//   object's method and not the other one
firstObj.someMethod();
// "I'm a method!"
secondObj.someMethod();
// "Different Method!"

In JavaScript, as you can see, methods and properties are basically the same thing. Each resides in the specific object it has been defined for.

Manually Setting Properties by Passing Arguments

If you want to manually set the properties of an object instance, you can pass them as arguments to the constructor function. There's nothing particularly special or revolutionary going on here:

// Set up the constructor to take inputs
function MyConstructor(prop, func) {
  this.someProp = prop;
  this.someMethod = func;
}


// Call the constructor as normal but with args
var myObj = new MyConstructor("bar", function() {...})


// Package the inputs into an object instead
//   to avoid having to specify all arguments
function MyConstructor(inputs) {
  this.someProp = inputs.prop;
  this.someMethod = inputs.func;
}


// Same deal, now just pass the options object
var defaults = {
    prop: "bar",
    func: function() {...}
}
var myObj = new MyConstructor( defaults );

Inheriting Properties from Another Constructor

You may want your instance object to inherit the properties of multiple constructors, for instance, if one constructor (e.g. "Dog") should theoretically inherit from another (e.g. "Animal"). This is easy by using call to run the second constructor from within the first constructor, which gives the instance the properties and methods of both its main constructor and the second constructor:

// Set up a basic Animal constructor
function Animal(name){
  this.name = name;
}


// Set up the Dog constructor to `call`
//   the Animal constructor function inside it.
// Recall that the first parameter of `call`
//   sets `this` for the function being run
// Note that you do NOT use `new` from within
//   the child object since we're just running
//   the Animal constructor as a regular function
function Dog(name, breed) {
  this.breed = breed;
  Animal.call(this, name);
}


// Test it out and inspect "McGruff" to verify
//   that the properties from BOTH constructors
//   have been passed onto the object
var mcGruff = new Dog("McGruff", "Doberman");
mcGruff;
//=> Dog { breed: "Doberman", name: "McGruff" }

Why does this work?

Remember that call allows you to run a particular function and explicitly pass in what this should be. This is important because, in the example above, we're calling the Animal constructor from inside the Dog constructor and setting this to be the Dog we are constructing.

You should be able to follow what happens next -- the Animal constructor gets run as a normal function and sets a bunch of properties to the new instance using this. In our example, that means that it tacks those properties onto the Dog object-in-progress. By the end of this process, we've got a new Dog, packed with both its own unique properties AND those of its parent and grandparent constructors.

3. Creating Objects with 'Object.create'

We've seen how to create single objects using the literal syntax and multiple objects using the constructor pattern but there is one last option.

The final way that objects can be created is by using the "shortcut" create method. Though using constructor functions is more common, building object instances with create is growing in popularity due to its similarities to how object creation works in other languages. It also allows you to create an object and assign its prototype in a single step, which we'll talk about in a future lesson.

This was introduced relatively recently so isn't available in browsers as old as IE5.

We'll provide just a quick glimpse of this method for creating object instances here. It will be much more useful and interesting when we begin talking about prototypes later on. For now, it's simply useful to remember this as the third way to create objects which is similar to using constructors:

// Create a simple blank object which doesn't inherit
//   from anything (so is an Object by default)
// ...We'll worry about inheritance later.
var myBlankObj = Object.create(null);


// Create an object which has the `foo` property
var myObj = Object.create(null, { foo: { value: "bar" } } )


// Test drive
myBlankObj;
//=> Object {}
myObj;
//=> Object { foo: "bar" }

Code Review

The important bits of code from this lesson

// Set up a simple constructor-style function
function Foo(val){ this.someKey = val; }


// Use it to build an object with `new` and inspect
var bar = new Foo("hello");
bar; //=> Foo {someKey: "hello"}


// Declaring a constructor function
function MyConstructor() {
  this.someProp = "value!";
  this.someMethod = function() { return "I'm a method!" } ;
}


// Building an object with a constructor
var myObj = new MyConstructor();


// Passing inputs to the constructor
function MyConstructor(prop, func) {
  this.someProp = prop;
  this.someMethod = func;
}
var myObj = new MyConstructor( "bar", function() {...})


// Using an options object instead
function MyConstructor(inputs) {
  this.someProp = inputs.prop;
  this.someMethod = inputs.func;
}
var defaults = {
    prop: "bar",
    func: function() {...}
}
var myObj = new MyConstructor( defaults );


// Allow the instance to receive the properties
//   and methods of both its constructor and
//   a second "parent" constructor
function Animal(name) {
  this.name = name;
}
function Dog(name, breed) {
  this.breed = breed;
  Animal.call(this, name);
}
var myDog = new Dog("Spot", "Bulldog");

Wrapping Up

You've learned three separate ways to create objects (though we'll only use the first two for now):

  1. Using the literal syntax to create "anonymous" objects
  2. Using constructors to create "instance" objects
  3. Using create to create "instance" objects

This gives you everything you need to work with objects effectively in upcoming assignments. Most of your objects will probably be innocuous literals until you discover a need to build more than one, in which case you'll likely employ a constructor.

Later on, when we start talking about more object-oriented concepts like inheritance, you'll begin working more and more with constructors and the create syntax.



Sign up to track your progress for free

There are ( ) additional resources for this lesson. Check them out!

There are no additional resources for this lesson just yet!

Sorry, comments aren't active just yet!

Next Lesson: ES6 Main Functionalities