Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the proper applications of these different methods of object creation in JavaScript

Tags:

javascript

oop

I'm more of a back-end guy than a front-end guy, but JavaScript intrigues me. I'm trying to wrap my head around what seem to me to be multiple different methods of modeling objects.

For the past few years I've been primarily been writing code that looks similar to this (assume jQuery is loaded):

var TicketForm = {

    elements: ['input', 'textarea', 'select', 'checkbox'],

    enable: function(form) {
        this.elements.forEach( function(el) {
            form.find(el).prop('disabled', false);
        });
    },

    disable: function(form) {
        this.element.forEach( function(el) {
            form.find(el).prop('disabled', true);
        });
    }
};

This way I can simply call TicketForm.enable($('#whatever')); to enable a particular form, very similar to a static method call in PHP.

I've been playing with closures in PHP lately, and I'm aware that they exist (and I'm using them) in JavaScript as well. I'm trying to really grasp the concept more thoroughly. After coming across this amazing script: http://codepen.io/stuffit/pen/KrAwx, I decided I wanted to make an effort to mimic the coding style of that author. Just attempting to copy his style, I rewrote my code like this:

var TicketForm = function() {
    this.elements = ['input', 'textarea', 'select', 'checkbox'];
};

TicketForm.prototype.enable = function(form) {
    this.elements.forEach( function(el) {
        form.find(el).prop('disabled', false);
    });
};

TicketForm.prototype.disable = function(form) {
    this.elements.forEach( function(el) {
        form.find(el).prop('disabled', true);
    });
};

However, When I call TicketForm.enable($('#whatever')); in this case, I get the error

Uncaught TypeError: Object function () {
    this.elements = ['input', 'textarea', 'select', 'checkbox'];
} has no method 'enable'

So I did a little digging on SO and found How does JavaScript .prototype work?. The second answer in particular is very enlightening, as I come from a class-concept background rather than a prototype-concept background. I also flipped through a few of these slides: http://ejohn.org/apps/learn/#65, which was also helpful. It turns out that all I had to do was create an instance of TicketForm, at which time it's methods became available to me:

var myForm = new TicketForm();
myForm.enable(form); // works as expected

I have three questions:

  1. Why, aside from personal coding style, would one choose either one of the methods above over the other?
  2. Why do I have to declare an instance of the object with the second method, while I don't with the first?
  3. Are there proper names for either of these coding styles?
like image 830
Ben Harold Avatar asked Jun 19 '13 20:06

Ben Harold


2 Answers

Your first method defines an object literal, basically creating a "singleton". If you need multiple instances of the same "class", you need a constructor function (or Object.create).

like image 124
bfavaretto Avatar answered Oct 07 '22 00:10

bfavaretto


In JavaScript objects are mutable by default. This means that unless you're using a modern JavaScript engine and someone intentionally prevented the object from being modified, you can always add, remove and modify properties in an object.

In the first case you're using special syntax that simplifies object creation. The {} syntax creates a simple object which is no more than an instance of Object. This, combined with the mutability of objects in JS, means the following snippets are all equivalent:

var TicketForm = {
  elements: ['input', 'textarea', 'select', 'checkbox']
};

var TicketForm = {};
TicketForm.elements = ['input', 'textarea', 'select', 'checkbox'];

var TicketForm = new Object();
TicketForm.elements = ['input', 'textarea', 'select', 'checkbox'];

Essentially using {} is similar to creating an instance of an object in a classical OOP language, while creating a constructor function is similar to using a class. In a constructor function and its prototype you define a blueprint that all instances of that constructor function (all objects that share that prototype) will adopt.

So it's not about style, but rather about what you need to create. If you need multiple copies of the same thing, you use a constructor function. If you need only one, just create a plain object, no need to follow an etiquette, make a singleton and sign everything by triplicate ;)

like image 2
juandopazo Avatar answered Oct 07 '22 00:10

juandopazo