pattern

Javascript objects: notation, prototype...

Introduction

Since the WEB 2.0 revolution we have it back: the heavy usage of JavaScript for websites and online-applications. We have AJAX and all these beautiful JavaScript frameworks like JQuery and Co - which helps building "rich client" online applications.

Most online application developers are familar with developing server side applications and using approved patterns and practices, such as "OOP", "MVC", "MVP" and "Unit-Testing", to ensure maintainable and clean code.

However since the UI of common webapplications requires more and more JavaScript its time to summarize some of the tricks for that good old scripting language.

Did you know?

  • JavaScript has no classes - but objects - which can be manipulated during "runtime"
  • objects can inherit from other objects
  • functions - and in fact nearly everything in JavaScript as well - are objects
  • all function objects have special properties like prototype or caller

Literal Notation for creating new objects

A simple object is created with the {} notation.
That's the shortest example - creating a variable and assigning an empty object to it:

//create new object:
var myobj = {};

Properties and functions can be added to that object with member operators: either the "dot notation" or the "bracket notation" (its both the same):

//create new simple property with dot notation
myobj.name = "Mustermann";
//create a function "getName"
myobj.getName = function() {return this.name};
//use the braket notation
myobj['firstname']="Max"

The same can be written in a more readable way - the following code will have exactly the same result. Properties and functions are written inside the {} brackets - separated with a comma (this syntax is also known from JSON):

var myobj = {
            name: 'Daniel',
            firstname: 'Max',
            getName: function() {          
                return this.name;
            }  
}

What happens here:

var myobj2=myobj;
myobj2.name='foo2';
alert(myobj.getName());

The variable myobj2 gets the reference to the object in myobj. Therefore changing the name with "myobj2.name" also changes the name in myobj - and the code will alert "foo2". That means creating a new object in this way is not possible (there are ways to copy simple objects - but functions are the better way to create object instances)

More about objects

In JavaScript nearly everything is a object. So "function", "Array", "Math"... are standard JavaScript global objects that are available in the global scope. Each object in JavaScript has certain common methods and properties. Even the environment of your JavaScript code is in a so called "global object". You can add subobjects and sub-properties to your object as shown above. The current context object can be accessed with the keyword "this".

Functions are more advanced objects

var myadvobj= function() { return 'hello world'};

This code creates a function object and assign this to the variable myadvobj. The syntax above is exactly the same as the better known: "function myadvobj() {  return 'hello world';}". As allready mentioned, functions are just objects with more possibilities than the simple object shown above, the function itself is the constructor function of the object. function objects have a number of predefined properties and methods (the most interesting one is "prototype" - thats useful to create new objects). Also the "new" operator is available for function objects and allows to create new object instances.

Using function objects and the prototype property

Lets start with that example:

var myadvobj= function() { 
this.name='my default name';
return 'hello world'
};

That code created the functionobject "myadvobj" -  the prototype property now has an object with the methods and properties of that function object:

console.log(myadvobj.prototype);

Creating new objects of the type "myadvobj" is easy:

var obj1=new myadvobj();

What happens is that the prototype property of "myadvobj" is used to create a new object "obj1". Note that "obj1" is no function object anymore - it's an object instance. That means something like this is not possible:

var obj2= new obj1(); //gives an error

To understand the prototype property look at the following example. Since functions are also objects you can also add methods on the fly:

myadvobj.subFunction=function() {return 'hello 1'};

You can do this for the prototype Object as well:

myadvobj.prototype.subFunction2=function() {return 'hello 2'};

What happens now:

var obj=new myadvobj(); //create instance of function object with new operator
alert(obj.subFunction()); // returns error - the function does not exist for the instance
alert(obj.subFunction2()); // returns "hello2"

Inheritance

There are several ways of implementing inheritance. With the prototype property we have the basis for implementing inheritance - for example the begetObject (by Douglas Crockford):

function begetObject(o) {
function F() {}
F.prototype = o;
return new F();
}
var childObject = begetObject(parentObject);

For more information please read this article

Conclusion: Singletons and Prototypes 

Just like in normal OOP, there are objects in JavaScript where only one instance is required (=singleton), and others where more instances are required (e.g. prototype).

Thus, if you only require one instance use the simple object notation - if you require more instances of a object use the function-objects and the new operator.

 

blog comments powered by Disqus
  1. Ann http://www.google.com 26.07.10 08:47

    Thanks for infromation!

  2. Daniel Pötzinger 28.12.08 17:57

    Hey.

    I am not sure if I understand you correct, but this:
    var obj = { init: function(){} };

    means "obj" is a singleton. You cannot have an independent obj2 with the same behaviour like "obj".

    For much cases it is ok to have just a singleton and group functions that belong together there.

    But there are use cases where it is nice to have independent objects (prototype) - for example if you need a kind of controller for widgets. And you want to have multiple seperate widgets (for each widget you need to save the individual state and want to have a certain behaviour)

    I will come up with a example later.

    Greetings

  3. Luca http://sktrdie.org 14.12.08 02:32

    I dont understand why you need to make many instances of an object when all you could do is still use the singleton pattern and have a method inside, that represents the constructor.. for example:
    var obj = { init: function(){} };
    vs
    var obj = function(){};

    you can still use the singleton and call obj.init() anywhere you need to do stuff with that object, this way you also have reference to other stuff inside "obj" that you can use anywhere else in the code.

    Is the prototype method more fast? I hope you understand my point. Let me know, Thanks.

blogroll