Client-side Scripting 101 Part 2: JavaScript OOP Basics

[Sorry this took so long to get out… I have been distracted by Windows 7 and am working between 2 OS’ on 1 machine… Win7 is now my primary OS and I didn’t have this post here… that and I’m now twittering doesn’t help either]

Ok, since in the first version of my last article I referenced the "prototype" property, it felt natural to begin by talking about JavaScript OOP basics. Now, I’m not going to try to define all the terms that usually get associated with the type of OOP used in JavaScript ("JS" hereafter). I want to give you --my valued reader-- with the practical knowledge. So let’s go over how JS as a language works:

JavaScript objects and types are extensible simply through use
What this means that to add a field to a JS object you need only reference the field. As a result there are 3 states of any value that you interrogate in JS: has a value (like 2, "v2", etc), is null, is undefined. "Null" means that the type member (property, field, method) is defined, but as of yet there is no value here. "Undefined" means that a type member does not exist as of yet. So let’s illustrate this with some code:

   1: var myObj = {};
   2: myObj.myNewProperty = null;
   3: var test1 = typeof(myObj.myNewProperty) == "undefined"; // returns false
   4: var test2 = typeof(myObj.myOtherNewProperty) == "undefined"; // returns true
   5: var test3 = (myObj.myNewProperty == null); // returns true

So what did we do there? Well, we created a new object; the "{}" is short hand for "new object()." BTW, that’s really JSON syntax (there’s more to that and we’ll cover it much later in another column). After creating an empty object we create a "myNewProperty" field and set it’s value to null (this field is created and is "defined"). Next we do a couple tests on the variable. The first test checks to see if the "myNewProperty" field on the created object is undefined (it is defined so test1 is false). The next test checks to see if the "myOtherNewProperty" field on the created object is undefined (since this is the first time we referenced it, the field is in fact undefined, so test2 is true). Finally we test to see if the "myNewProperty" field on the created object is null (which it is).

JavaScript object’s members can be referenced like a dictionary
In the example above we could have referenced the "myNewProperty" field like this:

myObj["myNewProperty"] = null;
What this means that with JS we can sometimes reference object members as if they were an array or more like a HashTable in .NET. The real importance of this is that JS objects are really strange characters in that they can be manipulated like both an object and an array/dictionary/hashtable. We’ll be briefly revisiting this syntax at the end of the Prototype section (but don’t blink… it’s really fast).

Function is used to create a class 
So thus far, we have extended objects and not classes. In JS we can use the Function type to define a class (I know that seems weird, but bear with me). Functions can contain other functions which have access to all the variables within them and any variable that it’s parent function can access. The constructor is actually the parent function. Let’s look at an example:

   1: function myClass()
   2: {
   3:   var privateVar = "Private variable";
   4:   this.publicVar = "public variable";
   5:   this.publicFn = function() {
   6:     // this fn can manipulate any of the above vars including the private ones
   7:     privateVar = "Private accessed by publicFn";
   8:     return "Public Function";
   9:   }
  10: }

myClass is a class that has a single private variable called “privateVar”. It has 1 public variable/field called “publicVar” and a public function called “publicFn.” We can create a variable of this type by doing the following:

   1: var myNewObject = new myClass();

The above example isn’t the way this is normally done though. Here’s why. That initial function/constructor looks really weird with the function declaration inside of it (imagine a public field declared after the a function declaration. It would get really messy quickly).

Prototype
So instead there is a special properties called “prototype” which can be used to add additional members to a function. Here’s an example of what that looks like:

   1: myClass = function()
   2: {
   3:     var privateVar = "Private Var";
   4:     this.publicVar = "Public Var";
   5: }
   6: myClass.prototype.publicFN = function()
   7: {
   8:     privateVar = "Private var accessed by function";
   9:     return "Public Function"
  10: }

We made a couple changes here. First we switched the order around for the function declaration. This is all perfectly legal. The function syntax creates an anonymous function and assigns it to the myClass (for instance). As you can see from the prototype syntax on line 6 that you simply extend the prototype object like we did earlier in the first code example.

We’re almost done. Let’s make a slight change to the more preferred syntax(and see our first very small example of JSON):

   1: myClass = function()
   2: {
   3:     var privateVar = "Private Var";
   4:     this.publicVar = "Public Var";
   5: }
   6: myClass.prototype = {
   7:     publicFn : function() {
   8:         privateVar = "Private Var changed by function";
   9:         return "Public Function";
  10:     },
  11:     get_PrivateVar : function() {
  12:         return privateVar;
  13:     }
  14: }

Not much has changed from the last version except one thing, and we’re setting the prototype function to an object (remember that the squiggly brackets are JSON syntax for object). The methods are mapped out using a “name:value” syntax. and is comma separated (you get a weird error if that comma is missing). We also went ahead and added one more new member which now exposes our private variable via a “property” get function.

There’s actually another variation on the syntax, but this is good enough for now. With this in hand you should be able too read just about any JavaScript object library and figure out where you can call things.

You might also notice that inheritance doesn’t look like it’s baked in… which is absolutely correct! Inheritance is not baked in. You have to use a separate framework to get it (it shouldn’t be that hard to see how one would get inheritance. One way would be to simply query the Parent type’s prototype and add those methods/properties to the child class; we can do all this by using that dictionary/HashTable syntax we mentioned above and a foreach loop. There are other ways as well but that is way beyond the scope of this tutorial --and really isn’t something you should care all that much about right now).

After all, being able to read this syntax was our overall goal (we want to use Script# to actually do our programming).

Next time we’ll cover Script# basics. (I’ll try not to take 3 weeks to get you the next installment)

Print | posted on Tuesday, February 03, 2009 4:50 PM

Feedback

# re: Client-side Scripting 101 Part 2: JavaScript OOP Basics

left by rowan at 2/17/2009 9:09 PM Gravatar
" "Null" means that the type member (property, field, method) is defined, but as of yet there is no value here".

I think it is worth mentioning that undefined can mean that a variable/property exists but it has yet to be given a value.

Consider:
var x;
alert(x===undefined);//TRUE

Same is true for objects
var myObj = {};
myObj.myNewProperty;
alert(myObj.myNewProperty===undefined);//TRUE

Slightly different for objects though.
alert(y===undefined);//Error as y has not been declared

var myObj = {};
alert(myObj.y===undefined);//No error and will be TRUE, even though have not referenced y before, does this create a y on myObj just by checking for its existence?



Title  
Name
Email (never displayed)
Url
Comments   
Please add 2 and 2 and type the answer here: