What style do you use for creating a "class"?

The method used when creating a class

Different approaches to creating classes in JavaScript are discussed, including the prototype approach, which allows instances to share a single copy of methods, and closures, which create separate copies of methods for each instance, useful for private methods but less memory-efficient. Object literals are also mentioned, although they are not suitable for inheritance. Ultimately, JavaScript does not have classes in the traditional sense, but class-like behavior can be simulated using constructor functions and prototypes, with the choice of approach depending on code requirements and developer preferences.

There are a few ways to get class-like behavior in javascript, the most common seem to be prototype based like this:

function Vector(x, y, x) {
    this.x = x;
    this.y = y;
    this.z = z;
    return this;
}

Vector.prototype.length = function () { return Math.sqrt(this.x * this.x ... ); }

and closure based approaches similar to

function Vector(x, y, z) {
    this.length = function() { return Math.sqrt(x * x + ...); }
}

For various reasons the latter is faster, but I've seen (and I frequently do write) the prototype version and was curious as to what other people do.

The approach you take when creating a class

My tests have shown that the closure based approach is slower. You have to instantiate a separate closure for each object. The prototype approach shares the methods with all instances.

7 Answers

Assigning functions to the prototype is better (for public methods) because all instances of the class will share the same copy of the method. If you assign the function inside the constructor as in the second example, every time you create a new instance, the constructor creates a new copy of the length function and assigns it to just that one instance.

However this latter technique is useful if you want each copy to have it's own copy, the main use of that being to do private/privileges methods which have access to private variables declared inside the constructor and inherited via the closure mechanism.

Douglas Crockford has a good summary.

There is also the object literal approach to the prototype:

var Vector = function(){};

Vector.prototype = {
  init:function(x,y,z) {
    this.x = x;
    this.y = y;
    this.z = z;
  },
  length:function() {
    return Math.sqrt(x * x + ...);
  }
};

var v1 = new Vector();
v1.init(1,2,3);

You can't set the literal prototype object if you're inheriting from something else, that would override the previous prototype.

You're correct - but in this case, "Vector" is a new object, so I didn't see any need to worry about inheritance issues.

Fortunately I get to use prototype _ js, which provides some nice wrappers. So you can do this:

var Person = Class.create({
    initialize: function(name) {
        this.name = name;
    },
    say: function(message) {
        return this.name + ': ' + message;
    }
})

Prototype _ js. Documentation: Defining classes and inheritance.

I don't think OP was asking for a wrapper that hides the details. He wanted to know why you would choose either approach, so he can weigh out the benefits.

Well, I don't really have an expert opinion on this. I usually end up using closures based approach just because it keeps the code simpler to manager. But, I have found myself using prototypes for methods that have loads of lines of code.

You also have the choice of:

function Vector(x, y, z) {
  function length() {
    return Math.sqrt(x * x + ...);
  }
}

Which is probably just as slow as example two, but it looks more like Java/C# and is a bit more explicit.

I'm a big fan of using John Resig's library for this. Lightweight, straight-forward, and you already know how to use it if you're familiar with the 'usual' object-oriented style.

There are no classes in javascript.

There are objects however. You don't need a class to create an object in javascript. It does have constuctor functions that you can invoke with new for example:

var james = new Person();

You can simulate class like behavior with:

prototype example:

function Car (type) {
    this.type = type;
    this.color = "red";
}

Car.prototype.getInfo = function() {
    return this.color + ' ' + this.type + ' car';
};

object literal example

var car = {
    type: "honda",
    color: "red",
    getInfo: function () {
        return this.color + ' ' + this.type + ' car';
    }
}

Prototype vs. Closure: The prototype approach is generally more memory-efficient as it allows all instances to share the same method, while closures create separate copies for each instance, which can lead to increased memory usage.

Private Methods: Closures are beneficial for creating private methods that can access variables defined within the constructor, providing encapsulation.

Object Literals: While object literals can be used to create objects, they are not suitable for inheritance, limiting their flexibility compared to prototype-based approaches.

No Traditional Classes: JavaScript does not have traditional classes; instead, it uses constructor functions and prototypes to simulate class-like behavior.

Choice of Approach: The decision on which approach to use depends on specific coding requirements and the developer's preferences, balancing simplicity, efficiency, and the need for encapsulation.

The prototype approach in JavaScript is more memory-efficient as it allows instances to share a single copy of methods, while closures create separate copies for each instance, which can increase memory usage but are useful for creating private methods. Object literals are not suitable for inheritance, limiting their flexibility. JavaScript lacks traditional classes, using constructor functions and prototypes instead to simulate class-like behavior. The choice of approach depends on code requirements and developer preferences, balancing simplicity, efficiency, and the need for encapsulation.

How can I enable disabled radio buttons?

Enable the disabled radio buttons

How can I enable disabled radio buttons? The following code works great in IE, but not in FF or Safari. I can't for the life of me work out why. The code is supposed to disable radio buttons if you select the "Disable 2 radio buttons" option. It should enable the radio buttons if you select the "Enable both radio buttons" option. These both work... However, if you don't use your mouse to move between the 2 options ("Enable..." and "Disable...") then the radio buttons do not appear to be disabled or enabled correctly, until you click anywhere else on the page (not on the radio buttons themselves). If anyone has time/is curious/feeling helpful, please paste the code below into an html page and load it up in a browser. It works great in IE, but the problem manifests itself in FF (3 in my case) and Safari, all on Windows XP. function SetLocationOptions() { var frmTemp = document.frm; var selTemp = frmTemp.user;…

Read more…

The difference in closing style - JavaScript

JavaScript: What's the difference in closure style

What's the difference in closure style. There are two popular closure styles in javascript. The first I call anonymous constructor: new function() { var code... } and the inline executed function : (function() { var code... })(); are there differences in behaviour between those two? Is one "better" over the other? Both cases will execute the function, the only real difference is what the return value of the expression may be, and what the value of "this" will be inside the function. Basically behaviour of new expression. Is effectively equivalent to var tempObject = {}; var result = expression.call(tempObject);…

Read more…

Getting the text from a drop-down box

Getting the text from a drop-down box

This gets the value of whatever is selected in my dropdown menu. document.getElementById('newSkill').value . I cannot however find out what property to go after for the text that's currently displayed by the drop down menu. I tried "text" but that didn't have the answer, does anybody here know? For those not sure, here's the HTML for a drop down box. <select name="newSkill" id="newSkill"> <option…

Read more…