Latest Updates

24
Latest Updates 1. Updated gallery slideshow script 2. [more] Teaching you how to create web pages With four sections covering HTML, CSS, JavaScript and web site design. If you don't know what those are, read the paragraph below. Teaching you how to produce web pages that everyone can use This seems to be an unusual idea. Creating pages that work on everyones' browser? Surely not! The idea of this site is to show you that it is not that difficult to do. If you work through the whole site, and in particular the section on web site design, you will be able to do it too. See my list of computers, operating systems, modems and browsers to see why it is important. What do HTML, CSS and JavaScript do? HTML formats web pages. It tells the browser when to start and end paragraphs and titles, and when to insert images and forms. It can also say what colours to make everything, and a few other basic styles like table borders, but in general, this should be done with CSS instead. CSS replaces many parts of HTML and is more customizable. It says what fonts, colours, sizes and effects to use including borders and backgrounds. It also allows you to position parts of the document exactly where you want them. JavaScript is a programming language that can be used to make parts of your document dynamic. You can use it to move parts of your document, change pictures, check forms and write dynamic content.

Transcript of Latest Updates

Page 1: Latest Updates

Latest Updates1. Updated gallery slideshow script 2. [more]

Teaching you how to create web pagesWith four sections covering HTML, CSS, JavaScript and web site design. If you don't know what those are, read the paragraph below.

Teaching you how to produce web pages that everyone can useThis seems to be an unusual idea. Creating pages that work on everyones' browser? Surely not! The idea of this site is to show you that it is not that difficult to do. If you work through the whole site, and in particular the section on web site design, you will be able to do it too. See my list of computers, operating systems, modems and browsers to see why it is important.

What do HTML, CSS and JavaScript do?HTML formats web pages. It tells the browser when to start and end paragraphs and titles, and when to insert images and forms. It can also say what colours to make everything, and a few other basic styles like table borders, but in general, this should be done with CSS instead.

CSS replaces many parts of HTML and is more customizable. It says what fonts, colours, sizes and effects to use including borders and backgrounds. It also allows you to position parts of the document exactly where you want them.

JavaScript is a programming language that can be used to make parts of your document dynamic. You can use it to move parts of your document, change pictures, check forms and write dynamic content.

JavaScript tutorial is based on '4th generation' and '5th generation' browsers with backwards compatibility.

Currently known '4th+ generation' browsers

Opera 4+ Gecko engine (Mozilla, FireFox, Netscape 6+ etc.) Internet Explorer 4+ KHTML and WebKit (Safari, Chrome, Konqueror, OmniWeb 4.5+) iCab ICEbrowser Escape 4+ NetFront 3+

Page 2: Latest Updates

Tkhtml Hv3+ Open TV Netgem 4 browser (NetBox) iPanel MicroBrowser Netscape 4+ OmniWeb (4.2-) Clue browser WebTV

More information.

What are 4th and 5th generation browsers?

5th generation browsers (also known as DOM browsers) are the latest and greatest browsers, that offer the most abilities and functionality, and are the most popular browsers in use today. 4th generation browsers are less capable, but are able to run things like menu scripts. Information is provided so you can still support the tiny proportion of Internet users who have not had the time, opportunity, money, desire or knowledge to upgrade yet, or who have not yet found a 5th generation browser they are comfortable with. The information can also be used to help you maintain older scripts which are still in use on your sites, as these can continue to function in modern browsers if written properly.

DisclaimerThe content of this site is provided 'as-is'. While I may offer support if you are having problems, or general queries about web development, I cannot be held responsible for any problems encountered or losses incurred through use of any of the information on this site, or any information that I send you in any way.

Please see my terms of use page for terms and conditions for use of my scripts.

Any opinions expressed on these pages are my own opinions only, and are not necessarily representative of the opinions of my employer or any organisation that I am affiliated with. They should not necessarily be read as facts. Neither I, my hosting service, my employer, affiliated organisations, nor anyone else on any planet in any corner of any universe can be held responsible for the opinions expressed on any of these pages.

This site was created by Mark "Tarquin" Wilton-Jones.

Important guidelinesFirst let's learn some important stuff. There are lots of browsers out there that cannot support JavaScript. Although browsers generally support more and more with each release, the language itself keeps evolving, and there is already a vast amount of the JavaScript language available for browsers to support. No browser will ever support all of it, and you cannot expect them to.

Page 3: Latest Updates

There are many reasons why people cannot or will not 'upgrade' to your chosen browser. A few are:

They are at work and they can only use the system default browser. They want to view pages more quickly so they use a text only browser. They are blind or have poor eyesight so they need a text only

browser/reader/Braille reader. They realise that the more extra features like JavaScript or VBScript you use, the

more you leave yourself open to becoming a target for viruses or vulnerability exploits.

They don't like the way some sites insist on taking over their control of the browser, opening popup windows, breaking the operation of the back button, preventing the context menu from working, or insisting on making things appear and disappear in a way that causes usability problems.

Whatever their reasons, you should not stop them from using your site. If your site uses JavaScript for navigation or content, then that navigation and content should be there without JavaScript enabled. Your JavaScript can extract content from the page, and do whatever it wants with that, but you should make sure that content is available without the script. If you want to use a script in way that you cannot simply extract the information from the static page, then you should use <noscript> to provide an alternative for people that cannot run your script.

There are also many browsers out there that you do not realise exist. I know of well over a hundred different browsers that support JavaScript to varying degrees. If your script uses something that browsers may not support, you should detect if the browser is capable of using it, and then fall back to an accessible alternative if it doesn't.

There is no magic formula for this, but the basic rules are that you should not detect a browser make or version. You will get it wrong, and you will mistakenly detect one browser and think it is another, ending up with you using the wrong code. You will make incorrect assumptions about current and future browsers, and you will cause problems for your users.

This tutorial should help you learn how to correctly detect capabilities, and wherever needed, it will show you how to work out when a browser cannot do what you need, so you can halt your script, or provide an alternative. When there are different ways to do the same thing, and some browsers only support one, while others support another, it will show you how to correctly work out which one to use.

Last modified: 4 September 2008

1. Next

This site was created by Mark "Tarquin" Wilton-Jones.

Creating objects

Page 4: Latest Updates

Netscape 4, IE 4 on Windows and Mac, and IE 5 on Mac do not support the instanceof operator.

Any function in JavaScript can be used to create custom object classes, simply by calling it using the keyword new. When called in this way, the special variable this inside the function references the new object that is being constructed (it normally refers to the 'current' object, which is usually window, except inside methods). The function should not return a value. The following function can be used as demonstrated to create an object of class myobject:

function myobject() { this.containedValue = 0; this.othercontainedValue = 0; this.anothercontainedValue = 0;}

var mything = new myobject();

And there you go, mything is now an instance of class myobject. It will have the following properties, all of which will be 0:

mything.containedValue mything.othercontainedValue mything.anothercontainedValue

You could also now write this:

myobject.prototype.newContainedValue = someValue;

This will cause all instances of class myobject will have the property newContainedValue with value someValue.

Use the instanceof operator to find out if your object is an instance of a given object class:

if( myvar instanceof Array ) { ... }if( myvar instanceof myobject ) { ... }

Creating an object with methods

Now I will give you an example showing you how to create methods for your objects. As an example, I will create a circle as my object. The methods will be

nameOfCircle.retArea()Returns the area of the circle (pi r2)

nameOfCircle.retCirc()Returns the circumference of the circle (2 pi r)

nameOfCircle.mvBy(xDis,yDis)Moves the circle by xDis in the x direction and yDis in the y direction

The following lines point the methods to functions that the object will use as the methods:

Page 5: Latest Updates

this.retArea = getTheArea; this.mvBy = mvCclBy; this.retCirc = function () { ... };

The third of these defines the method using an anonymous function in one line, and does not work in some early Netscape 4 releases. Note, it has a semicolon after the '}', and is one of the few places where this is correct practice.

function mycircle(x,y,r) { this.xcoord = x; this.ycoord = y; this.radius = r; this.retArea = getTheArea; //This next line uses an alternative syntax this.retCirc = function () { return ( Math.PI * this.radius * 2 ); }; this.mvBy = mvCclBy;}function getTheArea() { return ( Math.PI * this.radius * this.radius );}function mvCclBy(xDis,yDis) { this.xcoord += xDis; this.ycoord += yDis;}

/*create a mycircle called testcircle where testcircle.xcoord is 3and testcircle.ycoord is 4 and testcircle.radius is 5*/var testcircle = new mycircle(3,4,5);/*use the mvBy method to displace the centre of testcircle.move it by 2 in the x direction and 3 in the y direction*/testcircle.mvBy(2,3);//testcircle.xcoord is now 5 and testcircle.ycoord is now 7

window.alert( 'The area of the circle is ' + testcircle.retArea() );window.alert( 'The circumference is ' + testcircle.retCirc() );

The special 'toString' method

All objects have the 'toString' method, even if you do not define it yourself. The method returns a string representation of the object, and is automatically called whenever a string representation of an object is required, such as when you use alert(myObject);

In most browsers, this returns '[object Object]', although some more useful browsers return a string like this:

'{property1:value1,property2:value2,method1:function () { ... },etc.}'

However, for your own objects, you may wish to provide a special string that may provide more useful information. To do this, simply define the 'toString' method:

this.toString = function () { return 'Circle object; xcoord: ' + this.xcoord + ', ycoord: ' +

Page 6: Latest Updates

this.ycoord + ', radius: ' + this.radius;};

Advanced object techniques

These deal with concepts that are rarely used in JavaScripting. JavaScript is a more powerful programming language than most people make use of, but that is because in normal scripting, these powerful features are not really necessary. If you are just learning, or if you are interested only in day-to-day scripting, I suggest you move on to the next chapter.

Some of these techniques may not work in older browsers like early Netscape 4 releases.

Adding extra properties/methods using prototype Internet Explorer 5.2-, Safari 1.3-, Konqueror 3.3-, Netscape 4, and WebTV do

not implement the hasOwnProperty method.

Take the mycircle example from the top of this section (creating new objects). We have already created an instance of the mycircle class called 'testcircle'. And we can also assume that we have created a few other mycircles. Now, let us assume that we want to add another property to each circle. For example, we want each circle to have a 'texture' property. We could use this:

testcircle.texture = 'smooth';

And we could do this for each individual mycircle. But since we want to do this for all of them, it would be much more easy to give all instances the property at the same time. So we can use the 'prototype' property of the class constructor:

mycircle.prototype.texture = 'smooth';

Immediately, all of the mycircles that we have created will now inherit the new property:

alert(testcircle.texture);//alerts 'smooth'

We can add new methods the same way:

mycircle.prototype.setArea = function (oArea) { this.radius = Math.sqrt( oArea / Math.PI );};mycircle.setArea(5);

This is most useful with instrinsic (fundamental inbuilt) objects. For example, the regular expression construct /a[0-9]b/g is shorthand for new RegExp('a[0-9]b','g'); and in fact the same is true for all intrinsic object classes, such as String, Number and Boolean. So if, for example, we wanted to create a new method on all strings called 'reverse' that returned their contents in reverse order, we could do this:

Page 7: Latest Updates

String.prototype.reverse = function() { for( var oStr = '', x = this.length - 1, oTmp; oTmp = this.charAt(x); x-- ) { oStr += oTmp; } return oStr;};

The use of prototype could have been applied to create all of the methods of the mycircle object, not just new ones. This gives a mixed response to performance. It will not have to store individual copies of the methods for each instance of the object, so it may require less memory, but it will require the browser to search the current and parent scopes to find the methods. This may cause a marginal delay. Generally, you should use what is appropriate for your code, and not base this decision on performance (unless you are dealing with a very specific controlled environment):

function mycircle(x,y,r) { this.xcoord = x; this.ycoord = y; this.radius = r;}mycircle.prototype.retArea = function () { return ( Math.PI * this.radius * this.radius );};mycircle.prototype.retCirc = function () { return ( Math.PI * this.radius * 2 );};mycircle.prototype.mvBy = function (xDis,yDis) { this.xcoord += xDis; this.ycoord += yDis;};

In some cases, it may be desirable to work out if a property on an object is attached to the object instance itself, or somewhere in its prototype chain. In JavaScript, all objects have a method called hasOwnProperty that returns true if the given property is attached to the individual object instance. Of course, it is also possible to check if the object's constructor also has the same property with the same value as the object instance itself, but that can give the wrong result if separate properties exists with the same value on both the object instance and the prototype chain. The hasOwnProperty method accepts a single parameter; the name of the property as a string.

function myclass() { this.propertytwo = 2; this.propertythree = 3;}myclass.prototype.propertyone = 1;myclass.prototype.propertytwo = 2;

var myinstance = new myclass();myinstance.propertyfour = 4;

alert(myinstance.hasOwnProperty('propertyone'));//alerts false

alert(myinstance.hasOwnProperty('propertytwo'));//alerts true

Page 8: Latest Updates

alert(myinstance.hasOwnProperty('propertythree'));//alerts true

alert(myinstance.hasOwnProperty('propertyfour'));//alerts true

alert(myinstance.hasOwnProperty('propertyfive'));//alerts false

Public and private properties

This is a concept that is almost never used in JavaScript, and there is a good reason. It simply is not necessary. Even complicated scripts are almost never complex enough to require this level of control. However, many programmers familiar with other programming languages (such as Java or C++) often desire this behavior in JavaScript simply because it is a concept they are familiar with. This sort of concept is only really useful when putting together large projects from multiple pieces of code.

Say for example that I am producing a public functions library. A set of constructors and methods that people can include in their own projects (something that Java programmers use all of the time). Say for example that the mycircle constructor is included in it, so that you can create your own mycircles. Now say for example you try this:

var aCircle = new mycircle(5,6,'about 3mm');

That will work now (it's not a valid measurement, but my constructor will not argue), but later on when you try to use the methods that my class provides, it will fail. So I can check what you have provided, and make sure it is a valid number, and use a default value if it is not. But then you can say something like this:

aCircle.radius = 'some text';

Again, it would break (of course, it is your own fault, but in more complicated applications, it would be possible to make a mistake where this causes a real problem). So what I want to do is to not allow you to modify that property directly, and only allow you to change it using a method that I control:

this.setRadius = function (oRad) { if( typeof(oRad) == 'number' && oRad >= 0 ) { this.radius = oRad; } else { this.radius = 0; }};

An alternative situation where this can be important is if I am storing the information in one set of properties. I then upgrade my libraries, maybe adding some extra functionality. But in order to do so, I have to change the properties that I am using. If your script was relying on them existing in a specific format, and I have now changed that format, your script would fail. If I could protect those properties, and force you to use only methods, then I could do whatever I needed with the properties, and as long as I then change the methods to use the new properties, your script would keep working,

Page 9: Latest Updates

and you would not even need to know what I had changed or why. That way, we could each manage our own project, and not waste each other's time.

It would also help avoid possible conflicts between undisclosed properties, and your own scripting. For example, if you decide to temporarily assign a property to an object, but you were unaware that internally, my object constructor already used that property name, you would overwrite my object's property, and cause problems with the object.

This is what private properties are for. They do not allow scripts that use the contructor to use or modify the properties directly. They only allow the methods of the object itself to use and modify them. Unlike many other languages, JavaScript does not declare each variable type as 'public' or 'private'. It all depends on how you create them.

Saying 'this.propertyname' as I did above will create a public property. Any script can create an object then use and modify its properties directly. Using 'var' to define a variable in the constructor will create a private property. Note that unlike public properties, the private properties are then accessed, including from within methods, without the 'this.' prefix - just like a normal variable. This makes heavy use of JavaScript's scope functionality. Private variables can only be accessed from methods that are declared inline, and not externally referenced or created using the prototype construct. Methods of this kind are also known as privileged methods. An example of its use might be: this.mymethod = function () { alert( propertyname ); };

function myob() { this.property1 = 'value1'; //this creates a public property var property2 = 'value2'; //this creates a private property this.method1 = function () { alert( property2 ); };}var oneOb = new myob();alert(oneOb.property1); //alerts 'value1'alert(oneOb.property2); //alerts undefined (private property)oneOb.method1(); //alerts 'value2'

Similarly, you can also create private methods. These are simply a function that you create inside the constructor function. This may look confusing, but it works. The private function can only be called by the constructor itself, or by methods that are defined inline. Private methods can be used as public methods, if they are assigned to a public method constructor, and accessed using the public method constructor (as with 'method2' below).

function myob() { function cantBeSeen() { alert(secretValue); } var secretValue = ''; this.method1 = function () { secretValue = 'no surprises'; cantBeSeen(); }; this.method2 = cantBeSeen;}var oneOb = new myob();oneOb.method1(); //alerts 'no surprises'oneOb.method2(); //alerts 'no surprises'

Page 10: Latest Updates

For more information on private, public and privileged properties and methods in JavaScript, see Douglas Crockford's 'Private Members in JavaScript' page.

Sub-classes and class inheritance

This is also hardly ever used in JavaScript, despite its popularity in other languages. Take this as an example. I want to make a new type of object, that will store the data to represent a sphere (a ball - in case you don't know). Since a sphere is just a three dimensional circle, I would probably want to include all the methods I created earlier for the circle object; retArea to get the cross-section area, retCirc to get the circumference, mvBy to move it by a certain amount. Aditionally, I would probably want retVol to get the volume, and retSurf to get the surface area. I would also need to provide a z coordinate when creating the object, and again when calling the mvBy property.

So, I want to create a new type of object, based on the mycircle, but with a few aditions and modifications. I will call this new type of object a mysphere. Now, I could just rewrite all the code I already wrote for the mycircle and change the bits I need. But in a real-world application, this might be a lot of wasteful duplication, for only one or two modifications. So what I want to do is make the mysphere inherit all the properties and methods of the mycircle, then overwrite only the ones I want.

This effectively makes mysphere a sub-class of mycircle, and making the mysphere class constructor inherit from the mycircle class constructor is as simple as this:

function mysphere(x,y,z,r) { ... constructor code ... }mysphere.prototype = new mycircle();

In case you are wondering, the way it works is to actually create a mycircle, then assign that to the mysphere constructor prototype. As a result, the mysphere constructor has the mycircle object added to its prototype chain. What this means is that each time a mysphere is created, it will inherit the properties and methods of the mycircle object. It can then override any of these properties using its own prototype, or with properties and methods created within its own constructor. If any of these properties are subsequently removed (using the 'delete' keyword), the inherited ones will become available again. That also means that if the mycircle prototype is changed (properties are added or deleted, etc.), these changes are replicated down the chain, so the mysphere also inherits these changes.

Note that the prototype chain is established for each object as the object is created. Once an object has been created, its prototype chain cannot be changed (though new properties and methods can still be added to its parent classes, and those changes will be reflected in the object). Changes to its prototype chain will have no effect; it will still see the old prototype chain. The new chain will only be used for new instances of that class. This is also the case for the assignment of a new mycircle to the prototype of mysphere (which, as stated, creates a new instance of the mycircle class); any subsequent changes to the prototype chain of the mycircle class will not be reflected in the mysphere class. For this reason, it is very important to ensure that the prototype chain is built in the correct order, with class constructors and their prototypes set up before any child class is made to inherit from them. Properties and methods can still be

Page 11: Latest Updates

added to any class or parent class at any time after their own prototype chain has been set up.

The line that makes mysphere inherit from mycircle sounds simple enough. And at least, it would be, but you will remember that mycircle expected me to pass it some parameters that it would then use. Then I call my new constructor, and these parameters will not automatically be passed to the mycircle constructor function. I need to do this myself for each mysphere that I want to create. But since I am not passing these parameters when assigning the mycircle object to the mysphere prototype, I also need to ensure that the mycircle contructor stops before attempting to create its own properties. Instead of defining the public properties immediately, I will define them using a method (that I have decided to call getready), and if the required parameters have been passed (arguments.length), I will immediately call the method.

If the parameters are present, the mycircle constructor keeps working, and no-one needs to know that anything was changed at all. To make things easier later on, I will take all of the methods out of the constructor, and add them later using the prototype. That way, the mycircle prototype methods will always be available without me needing to create a new mycircle. Unfortunately, this also means that public and private properties are very hard (or impossible) to use. It's a trade off - one functionality for another.

function mycircle(x,y,r) { if( arguments.length ) { this.getready(x,y,r); }}mycircle.prototype.getready = function (a,b,c) { this.xcoord = a; this.ycoord = b; this.radius = c;};mycircle.prototype.retArea = function () { return ( Math.PI * this.radius * this.radius );};mycircle.prototype.retCirc = function () { return ( Math.PI * this.radius * 2 );};mycircle.prototype.mvBy = function (xDis,yDis) { this.xcoord += xDis; this.ycoord += yDis;};

Now, back to the mysphere constructor. I have already said how to make it inherit, but it still needs to run the mycircle.getready method to initialise the properties. To do this, we will need to reference the parent class prototype, and run the method ourselves. This also ensures that even if each parent class uses the same method name (getready), the correct one is always referenced. Since we can almost never be sure how many sub-classes we will need, it is useful to do it this way, and simply use the same method name for each, knowing that we will not have problems with name conflicts.

When running the method, we need to tell JavaScript that even though we are referencing a method for a different prototype, we want to run it as if it were a method of the object we are creating (to make sure that any properties it creates are added to the object we are creating). This could be done using the 'call' method or 'apply' method, but unfortunately, Internet Explorer 5 does not understand these, so I will assign it to a temporary property of the new object, and run it from there.

Page 12: Latest Updates

To reference the method from the parent class prototype, it would be possible to use the constructor's prototype chain to locate it (the property that references the constructor will, at this point, refer to the parent class - more on that later):

this.constructor.getready

However, that will only work for one level of inheritance, due to the way it is run as a method of the current object for all child classes. As a result, it is best to reference it by name, which will work no matter how many levels of class inheritance are used:

mycircle.prototype.getready

Note that when assigning the mycircle object to the mysphere prototype, it also overwrites the mysphere prototype constructor property. This is not a major problem, but some scripts use it, so we will put the reference back where we want it:

function mysphere(x,y,z,r) { if( arguments.length ) { this.getready(x,y,z,r); }}//inherit from the mycircle prototypemysphere.prototype = new mycircle();//put the correct constructor reference back (not essential)mysphere.prototype.constructor = mysphere;

mysphere.prototype.getready = function (a,b,c,d) { //reference the getready method from the parent class this.tempReady = mycircle.prototype.getready; //and run it as if it were part of this object this.tempReady(a,b,d); //now that all required properties have been inherited //from the parent class, define extra ones from this class this.zcoord = c;}mysphere.prototype.mvBy = function (xDis,yDis,zDis) { //override the existing method this.xcoord += xDis; this.ycoord += yDis; this.zcoord += zDis;};mysphere.prototype.retVol = function () { return ( 4 / 3 ) * Math.PI * Math.pow( this.radius, 3 );};mysphere.prototype.retSurf = function () { return 4 * Math.PI * this.radius * this.radius;};

And finally, to use it:

var testsphere = new mysphere(3,4,5,6);

alert( 'The cross-section area is ' + testsphere.retArea() );alert( 'The circumference is ' + testsphere.retCirc() );alert( 'The volume is ' + testsphere.retVol() );alert( 'The surface area is ' + testsphere.retSurf() );

Test this class inheritance script.

Page 13: Latest Updates

There is no limit to how many sub-classes can inherit from a class, and there is also no limit to how many levels of sub-classes can be created. As an example, I will create a ball class that will inherit from the mysphere class:

function ball(x,y,z,r,m) { if( arguments.length ) { this.getready(x,y,z,r,m); }}ball.prototype = new mysphere();ball.prototype.constructor = ball;

ball.prototype.getready = function (a,b,c,d,e) { this.tempReady = mysphere.prototype.getready; this.tempReady(a,b,c,d); this.mass = e;}ball.prototype.retDensity = function () { return this.mass / this.retVol();};

Test this class inheritance script.

The instanceof operator returns true when testing an object against any class in its prototype chain, so it would say that an instance of the ball class was also an instance of the mysphere class, and also the mycircle class.

For more information on sub-classes and class inheritance in JavaScript, see Kevin Lindsey's class inheritance page.

Static methods and properties

A static property (or method) is a property of the class constructor, not an individual instance of that class. For example, mycircle.myproperty instead of (new mycircle()).myproperty. While not often used in JavaScript, they are often encountered in other programming languages, and are covered here for those who are familiar with them in other languages. As with most objects in JavaScript, the functions used as class constructors can have properties added to them, and these will be public static properties:

function mycircle() { ... }mycircle.aStaticProperty = true;mycircle.aStaticMethod = function () { ... };

Making a private static property is significantly harder, as it is a concept that JavaScript (at least in widely supported implementations) simply does not recognise. However, it is possible to provide an approximate equivalent to this functionality by using an anonymous wrapper function to create a scope where the private "properties" are created as normal variables, then having that return another function that will be used as the constructor. As long as the constructor function is declared inside the anonymous function, it will have access to the private variables from the anonymous function's local scope when it is executed. This structure is described in the section on writing functions.

var mycircle = (function () {

Page 14: Latest Updates

var privateStaticVariable = true; function privateStaticMethod() { ... } function publicConstructor() { this.normalInstanceProperty = 1; ... alert(privateStaticVariable); }; publicConstructor.prototype.normalProperty = 2; return publicConstructor;})();mycircle.publicStaticProperty = true;mycircle.publicStaticMethod = function () { ... };

Singletons

The singleton is one of the design patterns that is commonly seen in other languages, and in a simplified format within JavaScript. The idea of a singleton is to have a class that can only have one object created from it. Every time a script tries to create another instance of that class, it returns the same copy as before, so if the properties are modified on one of them, then the other will also see the modifications. The use of singletons can be controversial, but I will not cover that here. This tutorial will only show you how to produce them.

In JavaScript, there is the ability to create a generic anonymous object to serve this purpose. It can either be created using new Object() or the shorthand { ... } syntax, and can then be given any properties or methods that are needed. However, this does have limitations; using a generic object means that it is not possible to use private properties. In most cases, this is functionality that is not needed, and the majority of scripts simply use a generic object. Instead of trying to constuct new instances of the object, scripts will just create another variable that references the object:

var mySingleton = { foo: 'bar', baz: 'qux', aMethod: function () { ... } };...var anotherReference = mySingleton;

If you feel the need for private properties, read on. With other languages, the expectation is to create a class constructor that refuses to be instantiated by other scripts, and provides a public static method that constructs the object the first time it is called, and returns the same object for each subsequent call. JavaScript, however, does not provide a way to prevent a class from being instantiated (at least in widely supported JavaScript). If it exists as a function, it can be called as a constructor.

It is tempting (and sometimes used) to simply use an anonymous function as the class constructor, construct it once, and use its scope to keep variables private. This is limited to normal private properties, and cannot be used for private static properties. The theory is that this enforces the singleton principle by preventing another attempt to reference and use the class constructor. This pattern fails to produce a singleton, however, as other code can simply use the singleton's constructor property to reference it - although you could override the singleton's constructor property, this can cause other problems later on if code needs to be able to use that to add properties to the constructor.prototype.

var mySingleton = new function () {

Page 15: Latest Updates

var privateStaticVariable = true; function privateStaticMethod() { ... } ...};

It is, however, possible to adapt the pattern used for private static properties, to create private properties for the singleton, while at the same time creating a proper singleton. Once again, an anonymous function is used to contain the private variables and functions. However, instead of returning a class contructor function, it just returns the single object:

var mySingleton = (function () { var privateStaticVariable = true; function privateStaticMethod() { ... } return { ... };})();

That is, of course, a very simple pattern, but it shows something important; by returning a generic object, it is not possible to use new mySingleton.constructor() to create a separate instance, as that would just produce a generic object. This particular format is quite awkward, however, as the generic object prevents the prototype from being used to cleanly add more properties and methods. It is very simple to extend it to make that possible, however, just by creating the class contructor function inside the anonymous function:

var mySingleton = (function () { var privateStaticVariable = true; function privateStaticMethod() { ... } function PrivateConstructor() {} PrivateConstructor.prototype.publicProperty = true; ... return new PrivateConstructor();})();

This now means that new mySingleton.constructor() will create a new instance of a PrivateConstructor object. However, the constructor function, when called in this way, is pulled out of the inner scope during that call, and as a result, it ends up with a relatively useless object that has none of the prototype's properties. Once again, the singleton principle is enforced. New properties can be created by modifying the mySingleton.constructor.prototype. The singleton can itself be used as the prototype for another constructor, to allow sub-classes to be created.

There are some reasons why this particular approach may not be favoured; specifically that it always creates the singleton even if it is never used. Some may also prefer to use a function call instead of having a global variable always created (though a function is still a global variable), as this may make it possible to change the implementation later to use a different design pattern instead of a singleton. It is possible to take care of both of these concerns, by returning a function instead of an object. That function can check if the singleton has been created yet, store it in a private variable, and return the instance. This has the small limitation that an instance of the object will need to be created by an external script in order to add properties or methods to the prototype, but this is a limitation that is unlikely to be a problem:

Page 16: Latest Updates

var getSingleton = (function () { var privateStaticVariable = true; function privateStaticMethod() { ... } function PrivateConstructor() {} PrivateConstructor.prototype.publicProperty = true; ... var onlyInstance; return function () { if( !onlyInstance ) { onlyInstance = new PrivateConstructor(); } return onlyInstance; };})();...var mySingleton = getSingleton();

Or an equivalent approach that assigns the function to a global variable instead of returning it (this may be preferred for clarity, or to allow you to put the class instantiation methods at the top of the anonymous function instead of the bottom of it):

var getSingleton;(function () { var onlyInstance; getSingleton = function () { if( !onlyInstance ) { onlyInstance = new PrivateConstructor(); } return onlyInstance; }; function PrivateConstructor() {} PrivateConstructor.prototype.publicProperty = true; ...})();

It is, however, possible to make the anonymous function return an object which can be used for prototyping directly, but this becomes quite messy. The PrivateConstructor can be made to inherit its prototype from the object that will be returned by the anonymous function. The singleton (when it is created) will then inherit any changes made to that object (in addition, it will inherit the getInstance method from the returned object, but this is harmless). I recommend that you avoid getting into a situation where you would need this functionality in a script.

var singletonMaker = (function () { var privateStaticVariable = true; function privateStaticMethod() { ... } var onlyInstance; var returnedObject = { getInstance: function () { if( !onlyInstance ) { onlyInstance = new PrivateConstructor(); } return onlyInstance; } }; function PrivateConstructor() {} PrivateConstructor.prototype = returnedObject; PrivateConstructor.prototype.publicProperty = true;

Page 17: Latest Updates

... return returnedObject;})();...singletonMaker.foo = true;var mySingleton = singletonMaker.getInstance();alert(mySingleton.foo); //true

For more information on this topic, see Kai Jäger's article about singletons in JavaScript.

ECMAScript 5

ECMAScript 5 adds several additional methods for custom objects, allowing you to control whether properties can be added, or obtain information about the object's prototype. ECMAScript 5 is not currently supported by enough browsers for it to be used in most practical applications. Even the parts that are supported by Internet Explorer 9+ are not available in quirks mode - the browser intentionally regresses to IE 6's scripting support. This means that generic scripts that are designed to work anywhere, will not be able to make use of the new functionality even once it becomes widely supported.

Last modified: 19 March 2011

1. Previous 2. Next

This site was created by Mark "Tarquin" Wilton-Jones.