The JavaScript Pseudoclassical Object Creation Pattern: A Step-by-Step Walkthrough

As I was progressing through the Launch School curriculum on Object Oriented JavaScript, things were going pretty smoothly. Until, that is, I encountered the Pseudoclassical Object Creation Pattern.

Jason Slusarchuk
Mar 23, 2018 · 7 min read

If you’re familiar with JavaScript, you’re likely aware that there are a number of different patterns that can be used to create an object: Factory Function, Object Linking to Other Objects (OLOO), and Pseudoclassical. Each method varies in complexity. Today I’m going to focus on the method I had the most trouble wrapping my head around: the Pseudoclassical pattern.

The biggest hurdle to comprehending this pattern well is that there are just so many moving pieces to keep track of at once. Add to this any preconceptions you may have regarding object instantiation coming from a class based programming language, and a couple of poorly named object properties, and it all becomes too much to hold in your head at once.

In order to fully grasp how it all worked, I had to first break the process of creating an object in the Pseudoclassical pattern out into its constitute components. Then, I watched how each of these components evolved throughout execution. Only after documenting the entire process was I finally able to reason what was actually going on and why.

This article assumes you already have some knowledge of object creation in JavaScript. Perhaps you already know of the pseudoclassical pattern but are struggling, like I did, to understand it.

Here is a list of those components and a quick definition of each:

1. the ‘constructor function’

// This is a functionfunction dog() {  this.speak = ‘bark’;}// And this is a constructor functionfunction Dog() {  this.speak = ‘bark’;}

2. the function ‘.prototype’ property

That .prototype object contains a property of its own called .constructor and it references the function itself.

Dog =  .prototype = {    .constructor = Dog  }

3. the object [[prototype]] property

puppy =  .[[prototype]] = {    .constructor = Dog  }

I’ve purposely left out some properties from the definitions above for the sake of making it easier to focus on the components most relevant to creating an object with this pattern.

With the preamble out of the way, let’s now go step-by-step through the process of creating a new object using the Pseudoclassical Object Creation Pattern.

1. Declare a ‘constructor function’ called Dog:

function Dog() {  this.speak = ‘bark’;}

This is pretty straight forward. We’re simply initializing a function called Dog. It’s just a regular function, but because we plan to use it to create Dog objects, we call it a constructor function.

I’ve included the property speak so that we can track exactly where properties and methods end up as they are added to the object (or made available to the object). This was a point of confusion for me.

2. Once declared, the Dog constructor function has these properties:

Dog =                      // These are the same Dog functions  .prototype = {    .constructor = Dog     // These are the same Dog functions  }

Here we are looking at the properties of the function Dog. Remember, functions are objects too so they can have properties of their own.

Upon being defined, the Dog method was automatically assigned the .prototype property and the object it points to.

3. Create a new object and assign it to a variable called ‘puppy’:

var puppy = new Dog();

4. When the ‘new’ command was invoked, the following sequence of events occurred:

this = {};

First, a brand new, empty object is created and assigned to this.

this.[[prototype]] = Dog.prototype;

Second, the new object’s [[prototype]] property is assigned a reference to the Dog function’s .prototype object. This will ensure that the new object now has a link back to the object from which is was created. In other words, this is the point where the new object gets a link to its parent’s DNA.

this.speak = ‘bark’;

Third, the Dog.prototype.constructor property is referenced (remember, that simply points to the Dog method) and invoked, at which point the method is executed with our new object (referenced by this) as the context. As we go through the method’s code, the property speak is added to the new object and assigned a reference to the String ‘bark’.

return this;

Finally, the new object is returned.

5. Once created, the new Dog object, ‘puppy’, has these properties:

puppy =  .[[prototype]] = {    .constructor = Dog  }  .speak

It’s worth noting that the puppy object’s [[prototype]] property is referencing the exact same object (highlighted in bold) that Dog.prototype references. Thus, we can now confirm that the the puppy object has a direct link to the DNA of its parent, the Dog function.

Also notice that the speak property was added to the puppy object itself.

6. Add a new property to a single dog object: = ‘running’;

Now, let’s say we wanted to add a new property or method to the puppy object. Simply add the property as you would to any other object.

7. Once added, the ‘puppy’ object now has these properties:

puppy =  .[[prototype]] = {    .constructor = Dog  }  .speak  .run

Notice that, once again, the property was added directly to the puppy object. We could call either of the puppy object’s methods as expected:

puppy.speak;   // returns 'bark';     // returns 'running'

8. Add a new property that ALL Dog objects can access:

Dog.prototype.jump = ‘jumping’;

We add the jump property to the Dog function’s .prototype object, not the Dog function object itself. If we added the property to the Dog function object, it would only be available to the Dog function object. We want to add the property to the Dog function’s DNA so that all Dog objects can access it, and that DNA is stored in the Dog function’s .prototype object.

9. Once added, the constructor function, Dog, now has these properties:

Dog =  .prototype = {    .constructor = Dog    .jump = ‘jumping’      // Property was added here  }  // Not here!

Notice that this time the new property was added to the Dog function’s .prototype object, not to the puppy object itself and not to the Dog function object either.

10. Now, the ‘puppy’ object has these properties:

puppy =  .[[prototype]] = {    .constructor = Dog    .jump = ‘jumping’  }  .speak  .run

We can now see that the puppy object has access to speak and run as they are properties of its own.

The puppy object also has access to the jump property via its [[prototype]] object. This is because the puppy object’s [[prototype]] property is pointing to the exact same object as the Dog function’s .prototype property (both highlighted in bold, above and below). Any property we add to the Dog.prototype object will be available to every other object that has access to that same Dog.prototype object. This includes all objects created with the Dog constructor function of course.

Dog =  .prototype = {    .constructor = Dog    .jump = ‘jumping’  }

11. If we were to now create a new Dog object, ‘puppy2’, it would have these properties:

puppy2 =  .[[prototype]] = {    .constructor = Dog    .jump = ‘jumping’  }  .speak

The puppy2 object has access to the jump property via its link to the Dog.prototype property. The puppy2 object also has access to the speak property that was added directly to the new puppy2 object when that object was constructed as described in step 4.

Other Considerations

There are at least two reasons:

  1. Adding the same behavior to every new Dog object is not very efficient. It means that each of those objects takes up slightly more memory because they’re all hauling around their own copies of the same behavior. By putting all of the common behavior into a single object, then sharing that object with any other object that needs access to that behavior, you’re maximizing the use of your available resources.
  2. The code will be easier to maintain when you’re consistent in terms of where an Object’s behavior is grouped. Having some of it in the Dog constructor method and some of it in the Dog.prototype object would not be ideal.

Advice on Next Steps

The way I’ve described things here is just one perspective out of many others available to you on the internet. What I would recommend, and what helped me as well, was reading through a few different articles on the subject in order to attack the issue from multiple fronts.

Here are a couple of resources you might consider (as written or recommended by my colleagues and instructors at Launch School):

If you have any questions (or corrections), please leave them in the comments below and I’ll be happy to help where I can.

Good luck and happy coding!

Ambitions of a Recovering Salesman

A chronicle of my journey from selling software to creating…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store