DEV Community

Cover image for 3 Ways to Create Objects in Object-Oriented JavaScript
Dr. Michael Garbade
Dr. Michael Garbade

Posted on • Originally published at blog.liveedu.tv

3 Ways to Create Objects in Object-Oriented JavaScript

(This article was originally published on my blog here ).

JavaScript is a powerful programming language that supports Object Oriented Programming (OOP).

In fact, in JavaScript, objects rule the day—from core features such as strings and arrays to browser APIs built using the language.

Bautista, a U.S.-based web developer who is passionate at teaching people about programming, emphasizes that “to take your JavaScript skills to the next level, you need to understand the object-based nature of the language.”

Here are three ways to create objects in Object-Oriented JavaScript (OOJS) programming:

1. Using object literals

In OOP, an object literal refers to a comma-split list of name-value pairs enclosed within curly brackets.

The names are strings, and the values are any primitive data types available in JavaScript such as arrays, strings, numbers, functions, and many others.

Usually, object literals are utilized in encapsulating code and wrapping it in an orderly package. This way, they prevent collisions with variables and objects found on the global scope.

With object literals, you can gather properties and methods together and make your code clean and uncluttered.

Here is an example:

var liveedu = {
  //declaring properties
student: "james",
  //declaring methods
watch: function() {
    console.log("learn new tech skills");
  },
};
//accessing methods and properties
liveedu.watch();
//output is learn new tech skills

JavaScript object literals are singletons, and they allow you to create objects conveniently and flexibly.

They save you from writing excessive lines of code.

For example, you can place an object literal anywhere in your workspace without including any previous setup, and it will still work well—something which can be very useful!

Although object literals are important, they do not support instantiation or inheritance.

If you want to make use of these features, you’ll need to use other techniques for creating objects.

2. Using object constructor functions

Constructor functions are the most conventional technique of creating JavaScript objects that rely on prototyping inheritance to utilize each other’s functionalities.

A key characteristic of these functions is that they can be instantiated and inherited from.

Let’s see an example of how constructor functions can be used in OOJS.

function Liveedu(student) {

      // properties

    this.student = student;

    // methods

    this.watch = function() {

      console.log(this.student + "learns new tech skills");

    }
}

// instantiating the object

var liveedu = new Liveedu("James ");

// accessing methods and properties

liveedu.watch(); //output is James learns new tech skills

console.log(Object.getPrototypeOf(liveedu)); // output is object

Here is what is happening on the above code:

  • Constructor functions are created just like regular functions. However, the difference is that the this keyword is employed for declaring properties and methods. In this case, this represents the object presently in the scope of the Liveedu function.

  • A new object referred to as liveedu is created using the new operator. Typically, new binds the newly created object to the this operator within the called constructor function. Consequently, the binding enables the liveedu object to acquire the properties and methods of the constructor function.

  • The liveedu object has a property referred to as prototype, which is where all inherited members are defined. So, when a function like watch() is called, the browser will move up the chain of objects and their respective prototype properties until it retrieves its value.

3. Using prototyping inheritance

JavaScript objects can also be created using the concept of prototypical inheritance.

Most modern browsers implement prototypes using a special property called proto, which is pronounced as dunder proto (shortened version of double underscore prototype).

Let’s use the following examples to illustrate how proto can be used in prototyping inheritance.

var liveedu = { 

    student: "james",

    watch: function() {

        return this.student + " is learning new skills";
    }
}

var livecoding = { 

    student: "felix",

    watch: function() {

        return this.student + " is learning new skills";
    }
}

As you can see on the above code, both objects have similar methods, which make the code look redundant.

Therefore, to make the objects share the same watch method, we can use the proto prototype property.

In other words, we can use the prototype to extend the properties of the objects.

Here’s is the rewrite of the above code:

var WatchProto = {

    watch: function() {

        return this.student + " is learning new skills";
    }

}

var liveedu = { 

    student: "james",

    __proto__: WatchProto

}

var livecoding = { 

    student: "felix",

    __proto__: WatchProto

}

console.log(liveedu.watch()); //james is learning new skills

console.log(livecoding.watch()); //felix is learning new skills

As you can see on the above code, both the objects share the same method that is defined in WatchProto. The liveedu and livecoding objects can directly access it, leading to cleaner and efficient code.

It’s important to note that proto is a new JavaScript ES6 syntax that may not be available in old browsers.

Alternatively, you can use the Object.create() method to create prototypes.

Here is an example:

var WatchProto = {

    watch: function() {

        return this.student + " is learning new skills";
    }

}

var liveedu = Object.create(WatchProto);

liveedu.student = "james";

Wrapping up

Understanding JavaScript objects is key to getting deeper into the ubiquitous language.

What’s your experience with implementing the object-oriented programming features of JavaScript?

Please share your comments and questions below.

Top comments (9)

Collapse
 
hugecoderguy profile image
Christian Kreiling

Cool post! My only suggestion would be to show prototypal inheritance through Object.assign, which tends to be a safer way to extend a function's prototype.

Collapse
 
educationecosystem profile image
Dr. Michael Garbade

Noted, maybe in another post, thanks!

Collapse
 
koresar profile image
Vasyl Boroviak

Hey Christian. I've just posed a comment here. It's about prototypal inheritance. Check it out. I'm sure you'll be interested. :)

Collapse
 
koresar profile image
Vasyl Boroviak • Edited

4. Using mixins for prototypes and for regular properties. More info here: stampit.js.org/

const stampit = require("stampit");

const Point = stampit({
  props: { // default property values
    x: 0,
    y: 0
  },
  init({ x, y }) { // kinda constructor
    if (x != null) this.x = x;
    if (y != null) this.y = y;
  },
  methods: { // that goes to the prototype
    distance(point) {
      return Math.sqrt(Math.abs(this.x - point.x)**2 + Math.abs(this.y - point.y)**2);
    }
  }
});

const point = Point({ x: 12, y: 42 });
point.distance({ x: 13, y: 42 }) === 1.0;

// kinda inheritance, but not really, see https://stampit.js.org/
const Circle = stampit(Point, {
  props: {
    radius: 1
  },
  init({ radius }) {
    if (radius != null) this.radius = radius;
  },
  methods: { // that goes to the prototype
    distance(point) {
      return Point(point).distance(this) - this.radius;
    }
  }
});

// Two different initializers will be executed here.
const circle = Circle({ x: 12, y: 42, radius: 1.5 });
circle.distance({ x: 12, y: 42 }) === 0.5;

const Tagged = stampit({
  props: {
    tag: ""
  },
  init({ tag }) {
    this.tag = tag || this.tag;
  }
});

const Colored = stampit({
  props: {
    color: "#000000"
  },
  init({ color }) {
    this.color = color || this.color;
  }
});

const GraphPoint = stampit(Circle, Tagged, Colored, {
  methods: {
    draw(ctx) {
      ctx.setColor(this.color);
      ctx.drawFilledCircle(this.x, this.y, this.radius);
      if (this.tag) 
        ctx.drawText(this.x + this.radius, this.y + this.radius, this.tag);
    }
  }
});

// FOUR different initializers will be executed here.
const graphPoint = GraphPoint({ 
  x: 12, 
  y: 42, 
  radius: 1.5, 
  color: "red", 
  tag: "start" 
});
graphPoint.draw(someDrawingContext);

const Line = stampit({
  props: {
    point1: Point({ x: 0, y: 0 }),
    point2: Point({ x: 0, y: 0 })
  },
  init({ point1, point2 }) {
    this.point1 = Point(point1);
    this.point2 = Point(point2);
  },
  methods: {
    middlePoint() {
      return Point({ 
        x: (this.point1.x + this.point2.x) / 2, 
        y: (this.point1.y + this.point2.y) / 2
      });
    }
  }
});

const line = Line({ point1: { x: 12, y: 42 }, point2: { x: 34, y: 40 } });

const GraphLine = stampit(Line, Colored, Tagged, {
  methods: {
    draw(ctx) {
      ctx.setColor(this.color);
      ctx.drawLine(this.point1.x, this.point1.y, this.point2.x, this.point2.y);
      if (this.tag) 
        ctx.drawText(this.middlePoint().x, this.middlePoint().y, this.tag);
    }
  }
});

const graphLine = GraphLine({ 
  point1: { x: 12, y: 42 }, 
  point2: { x: 34, y: 40 }, 
  color: "red", 
  tag: "March" 
});
graphLine.draw(someDrawingContext);

The idea is - separate concerns. The above has:

  • Point concern and all related functionality.
  • Circle concern and the related functionality. Circle is an extension of the Point.
  • Tag concern.
  • Color concern.
  • GraphPoint concern is Circle, Tag and Color concerns.
  • Line concern - it has two Points.
  • GraphLine - is the Line but with additional Tag and Color functionalities.

More info and examples are here: stampit.js.org/

Collapse
 
jochemstoel profile image
Jochem Stoel

I am curious what @joelnet has to say about this.

Collapse
 
joelnet profile image
JavaScript Joel • Edited

I think this a great article talking about Object Oriented Programming.

Though lately I have been focusing on Functional Programming, and I wrote an entire article that relates to this subject Functional JavaScript: Decoupling methods from their objects.

Collapse
 
jochemstoel profile image
Jochem Stoel

No, you wrote an article on the opposite of this subject.

Thread Thread
 
joelnet profile image
JavaScript Joel

^ that would be more accurate. go #FP!

Collapse
 
educationecosystem profile image
Dr. Michael Garbade

I'll read that post. Wonderful!