Join Now! It's FREE. Get full access and benefit from this site
Tuesday, 19 January 2010 12:51

In recent years, JavaScript has boomed, partly due to libraries that are developed to make building large scale JavaScript apps much easier. While in the past, it was a common argument that JavaScript was a basic language, and was very ’slap dash’ with no real foundation, this is no longer the case – especially with the introduction of high scale web applications and ‘adaptations’ such as JSON
(JavaScript Object Notation).
In today’s tutorial, I’ll provide you with a crash-course on working with objects in JavaScript.
JavaScript is an Object Orientated (OO) language and can have all that an OO language has to offer, albeit with some extra effort outside of the scope of this article.
function myObject(){
};
Congratulations, you just created an object. There are two ways to
create a JavaScript object: Constructor functions and
Literal notation. The one above is a Constructor function,
I’ll explain what the difference is shortly, but before I do, here
is what an Object definition looks like using literal notation.
var myObject = {
};
Literal is the preferred option for name spacing so that your JavaScript
code doesn’t interfere (or vice versa) with other scripts running on the
page, and also if you are using this object as a single object and not requiring
more than one instance, whereas the constructor function type
notation is preferred if you need to do some initial work before the object
is created, or require multiple instances of the object where each can be changed during the lifetime of the script. Let’s continue to build
both of our objects simultaneously, so we may visualize what the differences are.
Constructor version:
function myObject(){
this.iAm = 'an object';
this.whatAmI = function(){
alert('I am ' + this.iAm);
};
};
Literal version:
var myObject = {
iAm : 'an object',
whatAmI : function(){
alert('I am ' + this.iAm);
}
}
For each of the objects, we’ve created a property ‘iAm’ which contains a
string value that is used in our objects method ‘whatAmI,’ which alerts a message.
For those who don’t know, properties are variables created inside an object,
and methods are functions created inside an object.
Properties are variables created inside an object, and methods are functions created inside an object.
Now is a good time to explain how to use properties and methods (although you would already have done so if you are familiar with a library).
To use a property, first you type what object it belongs to – so in this case, myObject – and then to reference its internal properties, you put a full stop and then the name of the
property. So it’ll eventually look like myObject.iAm (this will return ‘an object’).
It’s the same for methods, except to execute the method, as with any function, you must
put parenthesis after it; otherwise, you will just be returning a reference to the function
and not what the function actually returns. So it will look like myObject.whatAmI()
(this will alert ‘I am an object’).
Now for the Differences:
There is also a difference between the way these two types of object declarations are used.
To use a literally notated object, you simply reference its variable name; so wherever it is required, you call it by typing:
myObject.whatAmI();
With constructor functions, you need to instantiate (create a new instance of) the object first. You do this by typing:
var myNewObject = new myObject();
myNewObject.whatAmI();
Let’s use our previous constructor function, and build upon it, so it does some basic
(but dynamic) operations when we instantiate it.
function myObject(){
this.iAm = 'an object';
this.whatAmI = function(){
alert('I am ' + this.iAm);
};
};
Just like any JavaScript function, we can use arguments with our constructor function;
function myObject(what){
this.iAm = what;
this.whatAmI = function(language){
alert('I am ' + this.iAm + ' of the ' + language + ' language');
};
};
Now, let’s instantiate our object and call its whatAmI method filling in the required
fields as we do so.
var myNewObject = new myObject('an object');
myNewObject.whatAmI('JavaScript');
This will alert ‘I am an object of the JavaScript language’.
Earlier, I mentioned the differences between Object Constructors and Object Literals, and that,
when a change is made to an Object Literal, it affects that object across the entire script, whereas when
a Constructor function is instantiated and then a change is made to that instance, it won’t affect any
other instances of that object. Let’s try an example;
First, we’ll create an Object literal:
var myObjectLiteral = {
myProperty : 'this is a property'
}
//alert current myProperty
alert(myObjectLiteral.myProperty); //this will alert 'this is a property'
//change myProperty
myObjectLiteral.myProperty = 'this is a new property';
//alert current myProperty
alert(myObjectLiteral.myProperty); //this will alert 'this is a new property', as expected
Even if you create a new variable and point it towards the object, it will have the same effect.
var myObjectLiteral = {
myProperty : 'this is a property'
}
//alert current myProperty
alert(myObjectLiteral.myProperty); //this will alert 'this is a property'
//define new variable with object as value
var sameObject = myObjectLiteral;
//change myProperty
myObjectLiteral.myProperty = 'this is a new property';
//alert current myProperty
alert(sameObject.myProperty); //this will still alert 'this is a new property'
Now let’s try a similar exercise with a Constructor function.
//this is one other way of creating a Constructor function
var myObjectConstructor = function(){
this.myProperty = 'this is a property'
}
//instantiate our Constructor
var constructorOne = new myObjectConstructor();
//instantiate a second instance of our Constructor
var constructorTwo = new myObjectConstructor();
//alert current myProperty of constructorOne instance
alert(constructorOne.myProperty); //this will alert 'this is a property'
//alert current myProperty of constructorTwo instance
alert(constructorTwo.myProperty); //this will alert 'this is a property'
So, as expected, both return the correct value, but let’s change the myProperty for one of the instances.
//this is one other way of creating a Constructor function
var myObjectConstructor = function(){
this.myProperty = 'this is a property'
}
//instantiate our Constructor
var constructorOne = new myObjectConstructor();
//change myProperty of the first instance
constructorOne.myProperty = 'this is a new property';
//instantiate a second instance of our Constructor
var constructorTwo = new myObjectConstructor();
//alert current myProperty of constructorOne instance
alert(constructorOne.myProperty); //this will alert 'this is a new property'
//alert current myProperty of constructorTwo instance
alert(constructorTwo.myProperty); //this will still alert 'this is a property'
As you can see from this example, even though we changed the property of constructorOne,
it didn’t affect myObjectConstructor, and therefore didn’t affect constructorTwo. Even if
constructorTwo was instantiated before we changed the myProperty property of constructorOne,
it will still not affect the myProperty property of constructorTwo, as it is a completely different
instance of the object.
Well, it depends on the situation. If you only need one object of its kind for
your script (as you will see in our example at the end of this article), then use an object literal, but if you need several instances of an object, where each instance
is independent of the other and can have different properties or methods depending on the way it’s constructed, then use a constructor function.
While explaining constructor functions, there were a lot of ‘this’ keywords being thrown around; as such, it’s important to talk about scope!
Now you might be asking ‘what is this scope you speak of’? Scope, in JavaScript, is function/object based, so that means, if you’re outside
of a function, you can’t use a variable that is defined within the function (unless you use a closure). This is done to prevent naming collisions, and also for garbage collection purposes.
There is, however, a scope chain, which means that a function inside another function can access a
variable defined in its parent function. Let’s take a look at some example code.
<script type="text/javascript">
var var1 = 'this is global and is available to everyone';
function function1(){
var var2 = 'this is only available inside function1 and function2';
function function2(){
var var3 = 'this is only available inside function2';
}
}
</script>
As you can see in this example, var1 is defined in the global object
and is available to all functions and object, var2 is defined inside function1
and is available to function1 and function2, but if you try to reference it from the global object
it will give you the error ‘var2 is undefined’, var3 is only accessible to function2.
So what does ‘this’ reference? Well in a browser, ‘this’ references the window object, so technically
the window is our global object. If we’re inside an object, ‘this’ will refer to the object itself however
if you’re inside a function, this will still refer to the window object and likewise if you’re inside a method
that is within an object, ‘this’ will refer to the object.
Due to our scope chain, if we’re inside a sub-object (an object inside an object), ‘this’ will refer to
the sub-object and not the parent object.
As a side note, it’s also worth adding that, when using functions like setInterval, setTimeout and eval,
when you execute a function or method via one of these, ‘this’ refers to the window object as these are methods of the window object; so
setInterval() and window.setInterval() are the same.
Now that we have that out of the way, let’s do a real world example, and create a form validation object.
First, I must introduce you to the addEvent function, which is a
combination of ECMAScript’s (Firefox, Safari, etc.. ) addEventListener() function and
Microsoft ActiveX Script’s attachEvent() function.
function addEvent(to, type, fn){
if(document.addEventListener){
to.addEventListener(type, fn, false);
} else if(document.attachEvent){
to.attachEvent('on'+type, fn);
} else {
to['on'+type] = fn;
}
};
This creates a new function with three arguments, to being the DOM object we are attaching
the event to, type being the type of event and fn being the function run when
the event is triggered. It first checks whether addEventListener is supported. If so, it will use that; if not, it’ll check
for attachEvent, and if all else fails, you are probably using IE5 or something equally obsolete. So
we will add the event directly onto its event property (note: the third option will overwrite any
existing function that may have been attached to the event property while the first two will add
it as an additional function to its event property).
Now let’s set up our document; well attempt to make the usage similar to what you might expect from a library like jQuery.
In jQuery, you would do:
$(document).ready(function(){
//all our code that runs after the page is ready goes here
});
Using our addEvent function, we have:
addEvent(window, 'load', function(){
//all our code that runs after the page is ready goes here
});
var Form = {
validClass : 'valid',
fname : {
minLength : 1,
maxLength : 15,
fieldName : 'First Name'
},
lname : {
minLength : 1,
maxLength : 25,
fieldName : 'Last Name'
},
validateLength : function(formEl, type){
if(formEl.value.length > type.maxLength || formEl.value.length < type.minLength ){
formEl.className = formEl.className.replace(' '+Form.validClass, '');
return false;
} else {
if(formEl.className.indexOf(' '+Form.validClass) == -1)
formEl.className += ' '+Form.validClass;
return true;
}
},
validateEmail : function(formEl){
var regEx = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
var emailTest = regEx.test(formEl.value);
if (emailTest) {
if(formEl.className.indexOf(' '+Form.validClass) == -1)
formEl.className += ' '+Form.validClass;
return true;
} else {
formEl.className = formEl.className.replace(' '+Form.validClass, '');
return false;
}
},
getSubmit : function(formID){
var inputs = document.getElementById(formID).getElementsByTagName('input');
for(var i = 0; i < inputs.length; i++){
if(inputs[i].type == 'submit'){
return inputs[i];
}
}
return false;
}
};
This is somewhat basic, but can easily be expanded upon.
To break this down: first we create a new property, which is just the string name of our 'valid' css class
that when applied to the form field, adds valid effects, such as a green border. We also define our two sub-objects, fname and lname,
so we can define their own properties that can be used by methods elsewhere; these properties are minLength, which is the minimum amount of characters these fields can have; maxLength, which is the max characters the field can have; and fieldName, which doesn't actually get used, but could be grabbed for
things like identifying the field with a user friendly string in an error message (eg. 'First Name field is required.').
Next we create a validateLength method that accepts two arguments, formEl, the DOM element to validate,
and the type, which refers to one of the sub-object to use (i.e. fname or lname).
This function checks whether the length of the field is between the minLength and maxLength range. If it's not,
then we remove our valid class (if it exists) from the element and return false; otherwise, if it is, then we add the valid class and return true.
Then we have a validateEmail method, which accepts a DOM element as an argument. We then test this DOM elements value against an
email type regular expression. Again, if it passes, we add our class and return true and vice versa.
Finally we have a getSubmit method. This method is given the id of the form, and then loops through all input elements inside the specified form
to find which one has a type of submit (type="submit"). The reason for this method is to return the submit button - so that we may disable it until the form is ready to submit.
Let's put this validator object to work on a real form. First we need our HTML.
<body>
<form id="ourForm">
<label>First Name</label><input type="text" /><br />
<label>Last Name</label><input type="text" /><br />
<label>Email</label><input type="text" /><br />
<input type="submit" value="submit" />
</form>
</body>
Next, let's access these input objects using JavaScript, and validate them when the form submits.
addEvent(window, 'load', function(){
var ourForm = document.getElementById('ourForm');
var submit_button = Form.getSubmit('ourForm');
submit_button.disabled = 'disabled';
function checkForm(){
var inputs = ourForm.getElementsByTagName('input');
if(Form.validateLength(inputs[0], Form.fname)){
if(Form.validateLength(inputs[1], Form.lname)){
if(Form.validateEmail(inputs[2])){
submit_button.disabled = false;
return true;
}
}
}
submit_button.disabled = 'disabled';
return false;
};
checkForm();
addEvent(ourForm, 'keyup', checkForm);
addEvent(ourForm, 'submit', checkForm);
});
Let's break down this code.
We wrap our code in the addEvent function, so when the window is loaded, this script runs.
Firstly, we grab our form using its ID, and put it in a variable named ourForm. Then we grab
our submit button (using our Form objects getSubmit method), and put it in a variable named submit_button,
and then set the submit buttons disabled attribute to 'disabled'.
Next, we define a checkForm function. This stores all the inputs inside the form field as an array, and we attach it to a
variable named.. you guessed it.. inputs! Then, it defines some nested if statements, which test each of the fields inside the inputs array against our Form methods.
This is the reason why we returned true or false in our methods, so if it returns true, we pass that if statement and continue onto the next,
but if it returns false, we exit the if statements.
Following our function definition, we execute the checkForm function when the page initially loads and also attach the function to a keyup event
and a submit event.
You might be thinking, why attach to submit if we disabled the submit button? Well, if you are focused on an input field and hit the enter key, it will
attempt to submit the form, and we need to test for this, hence, the reason our checkForm function returns true (submits the form) or false (doesn't submit form).
We learned how to define two different object types within JavaScript, and create properties and methods within them. We also learned a nifty addEvent function, and were able to use our object in a basic real world example: to validate a form.
This concludes the basics of JavaScript Object Orientation. Hopefully, this will start you on your way to building your own JavaScript library! If you liked this article, and are interested in other JavaScript related topics, post them in the comments as I'd be happy to continue writing! Thanks so much for reading.
Did you know that you can earn up to $600 for writing a PLUS tutorial and/or screencast for us? We're looking for in depth and well-written tutorials on HTML, CSS, PHP, and JavaScript. If you're of the ability, please contact Jeffrey at nettuts@tutsplus.com.
Please note that actual compensation will be dependent upon the quality of the final tutorial and screencast.
