Did You Know?
JavaScript can implement private members using clousures. More...

JavaScript constructors

Posted: January 30th, 2010 | Author: diegoquinteiro | Filed under: javascript | Tags: , | 5 Comments »


Fact: JavaScript is an object-oriented language.

So you can ask: where are the damn classes?

The truth is that there are no classes. JavaScript objects are soft: one can freely add, modify or remove properties from each of them individually in runtime. It’s a diferent way of programming object oriented, and a very powerful way.

The new operator

To master object orientation in JavaScript you need to clearly understand the new operator behaviour. This operators is used to create and initialize a new object given a function, called “constructor function”. For example:

function Person(name) {
	this.name = name;
}

var diego = new Person("Diego");
alert(diego.name); // Alerts "Diego"

var gabriel = new Person("Gabriel");
alert(gabriel.name); // Alerts "Gabriel"

Notice that diego and gabriel are not instances of Person class. Indeed, there’s no Person class, just a function named Person. Remember: there are no classes in JavaScript

When the new operator is used, an empty object is created and passed to the constructor function as the this reference. The function then can add members to that object by simple assignment, as in this.name = name.

Unless the function returns a not null object, the object this is returned and a reference for the constructor function is stored in the constructor property.

The result is very similar to class instantiation and we are tempted to call Person a class. It would be a real class if the object couldn’t be modified after its creation. JavaScript doesn’t works that way: objects can have properties and methods removed or modified anytime after their construction.

For didactic purpose, we’ll now implement the JavaScript new operator as a function:

var operatorNew = function (constructorFunction, args) {

	var object = {}, // creates an empty object
	    returnValue;

	// calls the function passing the object as 'this'.
	returnValue = constructorFunction.apply(object, args);

	if ((typeof(returnValue) !== "object" &&
	    typeof(returnValue) !== "function") ||
	    returnValue === null) {

		// if returnValue is not a not-null object returns 'this'
		returnValue = object;
		returnValue.constructor = constructorFunction;

	}

	return returnValue;
}

So the call…

var object = new ConstructorFunction(arg1, arg2, ...);

… will be the same as

var object = operatorNew(ConstructorFunction, [arg1, arg2, ..]);

… for any ConstructorFunction implemented in JavaScript.

PS: It won’t work with primitive types (String, Array etc). These are implemented in the browser, not in JavaScript code.

Analysing the operatorNew function we created, we realize that the new operator is just a shortcut. We can always create objects from literal notation then add members freely using no constructor at all.

Look at the following code:

var diego1 = new Person("Diego");

var diego2 = {}
diego2.name = "Diego";
diego2.constructor = Person;

var diego3 = {constructor: Person, name: "Diego"};

var diego4 = operatorNew(Person, ["Diego"]);

The objects diego1, diego2, diego3 and diego4 are equal!

Make no mistake: objects and construtors are in, classes are out.

That’s the JavaScript way.


5 Comments on “JavaScript constructors”

  1. 1 online said at 18:09 on March 13th, 2010:

    Por que nao:)

  2. 2 Guilherme said at 2:07 on January 23rd, 2011:

    Gostei dessa maneira, Diego. Também há um método de “simular” classes estáticas usando objetos {} no JavaScript, porém, assim não dá para usar variáveis privadas.

    Exemplo:

    var Estatica = {
    nome: ”,

    saudacao: function()
    {
    alert(‘Olá’ + this.nome + ‘!’);
    }
    };

    Estatica.nome = ‘Guilherme’;
    Estatica.saudacao();

  3. 3 frangossauro said at 13:11 on June 3rd, 2011:

    Bacana essa técnica , acho que o jResig a utilizava tb, não?

  4. 4 diegoquinteiro said at 3:47 on June 9th, 2011:

    acho que ele usa uma versão incrementada, pra proteger chamar o construtor sem o “new”

  5. 5 diegoquinteiro said at 3:57 on June 9th, 2011:

    isso não funciona muito bem na verdade, porque o “this” pode apontar pra outro objeto dependendo da forma que “saudacao” for invocada, tome cuidado!


Leave a Reply