Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Pragmatic OOP in JavaScript

JavaScript is the only language a web browser speaks; it is a given fact.
It's not a matter of choice if you are going to work with it, whenever you build
a browser app it is there. All script code might be hidden to you but there is
no ASP.NET, let alone Atlas (AJAX) without JavaScript. Recently I've been doing
a project which involved loads and loads of JavaScript. Being a C# addict myself I had
to get used to it but quite soon I found it had more power than I believed at
first. The first thing I wanted to know about my new programming environment is
how it supports OOP. When browsing for information on JavaScript and OOP the
problem seems to be that two disciplines have such a different background. The
majority of JS is produced by web-designers who have to write some code to get
their site working. The majority of OOP information is provided by "real"
programmers who look down on JS. And there are people like
Douglas Crockford to whom JavaScript is
the language where almost every way of programming meets. I don't share his
enthusiasm but his site is a must read and did provide me the best basis for
workable patterns.
As promised here is my, C# based, way of
OOP in JavaScript.

Getting started with JavaScript

Getting started is no big deal. At first sight you just start
typing ahead pretending to write in C#. But there is no compiler or unit testing
to validate your work; not until the code is interpreted at run time. As you can
do horrible things in JavaScript it does take a lot of discipline to write good
code. Also because the language itself is not as strict as C#. The following snippet of
code will run


function
CheckId()
{
    if (text1.value !=
"")
    {
        Id = ++text1.value;
    }
    else
    {
        id = -1;
    }
    return id;
}

An undeclared variables is created on the fly with global visibility. In this
case two, Id and id, are introduced. All script code on the webpage will see an Id a
an id variable (the different casing is a typing error). As JavaScript is
case-sensitive these are two distinct members. Both will keep their value over
calls to the function. But this id does not make much sense outside of the
function.

You limit the visibility of a member using the var keyword. This code
does the same without any of the side effects.


function
CheckId2()
{
    var id = -1;
    if (text1.value !=
"")
        id = ++text1.value;
    return id;
}

Note that variables and functions in JS do not have a type. The
value of the function result or the variable's values is formed by the
context. Which can lead to confusing things. These three expressions are
all true

1 + 2 == 3;
1 + '2' == '12';
1 + '2' ==  12;

The last one looks funny at first sight. But it makes sense when a
ToString()
is applied first to every member of the expression.

Objects in JavaScript

In C# an object is described by the class it's instantiated from. The class
is the type of the object. We just saw that the JavaScript language does not
have types. Objects in JS are created by a constructor function. An object in JS
is a dynamic collection of variables and functions. All methods in JavaScript
are functions, a procedure is in JS a function without a return statement. The constructor
function below creates a new
object with a Name and a Counter member.


function
MyObject()
{
    this.Name =
'A Javascript object';
    this.Counter = 0;
}

The this keyword marks the members as public accessible. You
instantiate an object using the new keyword.

<script>
    var myObj = new MyObject();
    function CountOnMyObject()
    {
        text1.value = myObj.Name + ' ' + (++myObj.Counter);
    }
</script>
<input type="text" size=90 id ="text1" />
<input type="button" value = "Debug" onclick="CountOnMyObject()">
 

When the page is loaded the new object is created. On every click of the
button the count is raised and the object returns it's name and count. Here we
have the base of object orientation, the possibility to bundle data and
functionality at work.

There are several ways to add methods to the objects. What you will find most
is a declaration which adds a function to the so called prototype of the object. These functions can
access the other members of
the object..


function
MyObject()
{
    this.Name =
'A Javascript object';
    this.Counter = 0;
}


function
MyObject.prototype.DoubleCount()
{
    return
this
.Counter * 2;
}

The DoubleCount() function returns twice the current value of the
Counter
member.

As said, JavaScript objects are a dynamic collection of members. These
members can be variables or functions. Any piece of
code can add a member on the fly. This can be done inside an existing member of the
object.


function
MyObject.prototype.DoubleCount()
{
    this.OnTheFlyMember =
'Set';
    return
this
.Counter * 2;
}

The result is that myObj.OnTheFlyMember is undefined until the first
time myObj.DoubleCount() is called.

But it can even get greasier than that. Also a snippet of script consuming
the object can add a member on the fly

<script>
    var myObj = new MyObject();
    function AddMemberToMyObject()
    {
        myObj.MemberFromScript = 'Hello from
a snippet of script';
    }
</script>
 

We will see later the not just member variables but also member functions can
be added or altered. To some people this dynamic nature of JavaScript is a bliss which opens the
doors to great ways of programming. I'm not sure about that, there are other
languages in case I would dive into that. Me and other mortals just need plain
simple, maintainable and easy to understand code. Object orientation is a step
towards that but the OO we have seen so far is no more than a bundling of
variables and functions with a public visibility.

<Update>Part 2 further discusses prototype</update> 

What makes objects far easier to
work with is encapsulation. Not just hiding the implementation of the method but
also hiding all internal data inside the object and all helper methods without
any relevance to the object's consumer. An object should only expose those
members which are of relevance to the consumer. This is done in
JavaScript using a slightly different syntax.

Now all functions are defined in the constructor function.


function
MyObject()
{
    var name =
'A Javascript object'
;
    var counter = 0;

    this.Count
= function()
    {
        counter++;
    }

    this.Name
= function()
    {
        return
name + ' with a count of ' + counter;
    }
}

Using the var keyword the name and counter's visibility
are limited to the constructor function. As the exposed members this.Count
and this.Name are also declared inside the constructor function they can
reach the private vars. They are named privileged members. The members
declared on the prototype are named public. To the script consuming the
objects there is no difference except when it comes to working with the
prototype, something we will meet when taking a look at inheritance. The object exposes public and
privileged methods and encapsulates
the private vars.

Also a helper method can be a private member. It is used by the object's
members but is not visible by the object's consumer.


function
MyObject()
{
    var name =
'A Javascript object'
;
    var counter = 0;

    function
capFirst(aString)
    {
        var str1
= aString.substr(0,1);
        var str2
= aString.substr(1);
        return
str1.toUpperCase() + str2.toLowerCase();
    }

    this.Count
= function()
    {
        counter++;
    }

    this.Name
= function()
    {
        return
capFirst(name + ' with a count of ' + counter);
    }

    this.AnotherName
= function(anotherString)
    {
        return
name + ' ' + capFirst(anotherString);
    }

}

Now we have objects which can hide data and implementation and expose just
that what is of interest to the consumer. Just like the .net object you're used
to.

Methods, overloads and properties

In a language like C# you have overloads, that is multiple versions of a
method each with a distinct parameter list. There is no such thing in
JavaScript. The function with a matching name is called passing it all parameters. Even when the
parameters are not specified in the function declaration they are available in
the function's implementation via the arguments keyword. This AnotherName method declares only 1 parameter.


function
MyObject()
{
    this.AnotherName =
function(anotherString)
    {
        return
arguments.length;
    }
}

When you use it with a longer parameter list, like this:

text1.value =myObj.AnotherName(text2.value, 'Boe', 'Blub',
9);

the AnotherName method will still be hit and it will return 4 .
You can use something like overloads in JavaScript but all implementation has to
be done within one method. It has to inspect the number and content of the arguments actually passed and
act accordingly.

To have the kind of object you're used to, where methods can reach private
data, requires privileged members. What the JavaScript syntax in such a
declaration actually does is
assign a function variable to a member of the object

this.MemberName =
function(params)

This dynamic way JS mixes code and data can hit back when you look at
properties. The constructor function below initiates a property Name and a
privileged method AnotherName.


function
MyObject()
{
    this.Name =
'A Javascript object';

    this.AnotherName
= function(anotherString)
    {
        return
'Another ' + anotherString;
    }
}

The consumer can read and set the Name property and call the
AnotherName
method.

text1.value = myObj.Name;
text2.value = myObj.AnotherName(text2.value);
text3.value = myObj.AnotherName;

The third statement is also valid. The object has besides the method
AnotherName()
also a  property AnotherName (without
parenthesis). The property will return the implementation of the AnotherName
method. The first time you meet this, for instance when you forget the
parenthesis in a method call it will make you scratch your head. The bad thing
is that you can also set this method property from code. Needless to say that
this is the way to have your carefully crafted code wrecked by consuming code.
Or altered, which is a next subject.

Static members

A static member is a member which is available without first creating an
object instance. JavaScript does have static members. They are declared outside of the
constructor function.


function
MyObject()
{
    this.Name =
'A Javascript object';
}

MyObject.MyStaticProp = 'This
is a static property'
;


function
MyObject.MyStaticFunction()
{
    return
'This is a static function'
;
}

You use them in your code by using the constructor function's name as a
prefix.

text2.value = MyObject.MyStaticFunction();

The usability of static members is limited as they cannot be used by the
privileged members. But they are a nice
way to organize a bunch of related functions into a class.

Inheritance

Inheritance is the weak spot in JavaScript's OOP implementation. The language
itself does not include the idea. Scattered over the web you will find a wide
variety of hacks to implement it. Harry Fuecks tries to give
an overview
and
does provide an, at first sight, elegant solution himself. The main problem with
all the implementations, including his, is that they work with the prototype and
thus only work for public members. The big problem we just saw with public
members is that they cannot work with encapsulated private members. The way to
keep your objects clean is using privileged members, that was having all code in
the constructor function. The implementations found on the web don't work with these
privileged members.

A reason for inheriting from a base class is polymorphism, where you pass
an object of a derived class to code expecting an object of the base class. As
JavaScript just tries at runtime if the object has a member with a matching
name, polymorphism will always work as intended. Another reason for inheritance is
changing the behavior by overriding members. We have seen that you can add or
replace any member of a JavaScript object on the fly. Instead of inheriting you
can aggregate an object, using a base class to implement things. Take these
creatures


function
Animal(named)
{
    var name = named ? named :
'Unknown';
    this.Name =
function()
    {
        return
name;
    }

    this.MakeSound
= function()
    {
        return
'That\'s the ' + name + ' sound';
    }
}


function
Cat()
{
    var base =
new Animal('Cat');

    this.Name
= base.Name;
    this.MakeSound =
function()
    {
        alert('Mew');
        return
base.MakeSound();
    }
}

The Animal constructor function provides an object with basic
functionality. The Cat constructor creates an Animal object,
passing in a value for the name. The Cat constructor exposes the animal's
Name function and provides an own implementation of
the MakeSound function which augments the base implementation.

<Update>Part2 discusses a variation</update> 

Most hacks
on the web are able to publish all public
methods in one go using the prototype. I have to explicitly re-publish every
privileged member. But the members of my object can keep working with shared
private var's; provided the members are in the same class, the Cat constructor
cannot see the Animal name var. I need some extra lines but this is a
price I'm quite willing to pay for a better encapsulation.

Conclusion

The four tenants of OOP programming are abstraction, encapsulation,
inheritance and polymorphism. Judging JavaScript on each of them

  • Abstraction is met. The object consumer only sees published members, not
    the implementation.
  • Encapsulation is met. Not only the code but also private data can be
    hidden from the object consumer
  • Inheritance is not met, but thanks to JavaScript objects being dynamic a
    simple and pragmatic work-around is possible
  • Polymorphism is in the core of the language.

The main point of JavaScript to me is being able to work with it in a
pragmatic manner and have simple well structured code. Which is possible as long
as I restrict myself.

 

This entry was posted in ASP.NET, Coding. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • blah

    You can guy check this library:
    http://code.google.com/p/jsclassextend/
    It’s versy small and provides very simple way to play with oop in javascript.
    Sample class:
    var SClass = JS.Class({
    //class body
    });

  • Pablo

    Great article. Thanks.

  • http://codebetter.com/blogs/peter.van.ooijen/ pvanooijen

    http://blogs.acceleration.net/russ/articles/1743.aspx ?

    First hit on a google search “javascript hashtable remove”

    JFGI

  • vashisht

    Hi

    Can u please guide me like how to remove the object item in java scaript.

    var hash=new Object();

    function getValue()
    {

    hash[‘a’]=7;
    hash[‘bj’]=3;
    alert(hash[‘bj’]);

    /* i did thsi by assigning the null value*/
    hash[‘b’]=null;
    /*********************************************/
    please guide how can i remove the hash[‘b’] kind of key
    /********************************************/

    if(hash[‘dddjjj’])
    {
    alert(“yes”);
    }
    else
    {
    alert(“no”);
    }

    }

    getValue();

  • http://codebetter.com/blogs/peter.van.ooijen/ pvanooijen

    Expose the functionality using COM works, as JS knows how to work with COM objects. It is also possible to directly addres an embedded object in your browser. The public properties and methods can be addressed.

  • Mitesh Shah

    Hey just wanted to ask how can i retrieve my C# object using javascript.
    i.e pass a C# object to javascript

  • http://blog.freelancing-gods.com Pat Allan

    Ah, I missed the details of Sergio’s comment. Seems mine was unnecessary.

  • http://blog.freelancing-gods.com Pat Allan

    Hi Peter

    I’m not certain, but my understanding of the difference between declaring methods of objects via Class.prototype.methodName and function Class() { function methodName(); } is that the former is much better for memory usage in the browser.

    Keep in mind I’m not certain about this, but I *think* when instances of the object are created, with the Class.prototype it doesn’t store a copy of every function in memory for each instance, whereas the other way of doing things means every instance keeps track of it’s own copy of the methods – so having a lot of objects uses up a *lot* more memory.

    That said, I’m not sure. Thanks for the clear discussion around this though :)

  • http://codebetter.com/blogs/peter.van.ooijen/default.aspx pvanooijen

    thanks everybody for the idea’s. A way to fake inheritance is a good subject to dive deeper into. I’ll come back on that.

  • Michael Urquiola

    I’ve been doing OOP with JavaScript for a long time. A few tips.

    I like this way of encapsulating functions in objects.

    function MyObj(){
    this.myFunc = _myFunc;
    function _myFunc(){
    }
    }

    Often times you need a pointer to the object you’re a part of within a function, in cases where your called from say an event handler.

    function MyObj(){
    var curObj = this; //set curObj to MyObj on creation
    this.myProp = true;
    this.EventHandler= _EventHandler;

    function _EventHandler(){
    //”this” when called from an event is the object raising the event “textbox”
    //use curObj to get at properties and functions in the MyObj context
    if (curObj.myProp) //do something
    this.style.backgroundcolor = “blue” //change the background color of the text box

    }
    }

    obj = new MyObj()
    textbox.onclick = obj.EventHandler;

  • Sergio Pereira

    Great post. I salude you for putting this together and helping lots of developers that are starting to go through the same challenges you experienced.
    Inheritance: Now try creating 2,000 Cat objects and see all those method definitions being multiplied in memory. To mimic inheritance, you should really try your best to work with the ‘prototype’ property of your class. That’s what the prototype.js library and many others do. Dean Edwards has some interesting works in this subject, most notably the Base.js implementation: http://dean.edwards.name/weblog/2006/03/base/

  • http://codebetter.com/blogs/peter.van.ooijen/default.aspx pvanooijen

    Jeremy,

    Nice, that works as well. Even better because now I don’t have to republish.
    It’s the constructor returning another object (an altered base), not this.

    return base;

    I’m not sure if I would call it inheritance. It’s in all cases closer than my approach.

    Indeed, every DOM object can be given the treatment i’ve lined out. Good to mention.

  • http://codebetter.com/blogs/jeremy.miller jmiller

    Peter,

    Maybe I’m not reading close enough, but why is it that you don’t think JavaScript supports inheritance? You can do this:

    function Animal(named)
    {
    var name = named ? named : ‘Unknown';
    this.Name = function()
    {
    return name;
    }

    this.MakeSound = function()
    {
    return ‘That\’s the ‘ + name + ‘ sound';
    }
    }

    function Cat()
    {
    var base = new Animal(‘Cat’);

    //base.Name = base.Name; <– unnecessary
    base.MakeSound2 = base.MakeSound; // could probably do this another way

    // override away
    base.MakeSound = function()
    {
    alert(‘Mew’);
    return this.MakeSound2();
    }

    return base;
    }

    Yes, calling base.Anything() is clumsy, but how often do you really need that?

    You might also point out that you can take any DOM object, i.e. a Textbox, dropdown, span, div, whatever and tack on additional properties and methods at will. I doubt that most people realize that.