Selfhtml - JavaScript 1.5 Guide - JavaScript 1.5 Reference - Gecko DOM Reference - M$ HTML and DHTML Reference - Dojo Toolkit - Web Applications and HTML5 - Standalone Javascript
Within functions always prefix variables with var
, otherwise they become global! See Avoid Global namespace
A string can be an instance of the String
class or a string literal. More
There is no difference between 'A string'
and "A string"
More
A string literal is temporarely converted into a String
object as soon as you apply methods of String
class to the string literal.
var s1 = "foo"; //creates a string literal value var s2 = new String("foo"); //creates a String object
var a= "al" + "pha" // a == "alpha" a += "bet" // a = "alphabet"
Because Strings are ojects, String comparison is the same as object comparison
String length: var len = mystring.length;
An Array is an instance of the Array
class. More
var arr= new Array(element0, element1, ..., elementN); var arr= [element0, element1, ..., elementN]; var arr= new Array(arrayLength); var arr= [];
Array length: var len = myarray.length;
function Point(x, y) {this.x=x; this.y=y;} Point.prototype.toString = function() {return "("+this.x+"/"+this.y+")";} Point.prototype.shift = function(dx, dy) {this.x+=dx; this.y+=dy;} var p = new Point(3,4); document.write("p:"+p.toString());
(closures see below)
function makePoint(x, y) { return { toString: function() {return "("+x+"/"+y+")";} shift: function(dx, dy) {x+=dx; y+=dy;} };} var p = makePoint(3,4); document.write("p:"+p.toString());
Objects are passed by refernce
function Point(x, y) {this.x=x; this.y=y;} Point.prototype.clone= function() {return new Point(this.x, this.y);} Point.prototype.toString= function() {return "("+this.x+"/"+this.y+") ";} var p = new Point(3,4); var pr = p; // a reference to p var q = p.clone(); // a new Point instance with the same coordinates as p p.x= 9; p.y=-2; // change content of p document.write("p:"+p.toString()+ "pr:"+pr.toString()+ "q:"+ q.toString()); // result: p:(9/-2) pr:(9/-2) q:(3/4)
function MyClass() { // constructor this.method1= function(arg) {/* code */}; // method }
function MyClass_method1(arg) {/* code */} // method function MyClass() {this.method1= MyClass_method1} // constructor
Not recommendable, because
this
function MyClass() {} // constructor MyClass.method1= function(arg) {/* code */} // method
Not possible, causes an js-error if called from an MyClass instace. This is a static method, see below
function MyClass() {} // constructor MyClass.prototype.method1= function(arg) {/* code */} // method
Seems to be the best solution
function MyClass() { // The constructor this.publicVariable= 10; // A public instance variable } MyClass.prototype.publicMethod= function() { // A public (instace) method document.write(this.publicVariable + 1 + ' '); document.write(MyClass.publicVariable + 1 + ' '); document.write(this.publicStaticVariable + 1 + ' '); document.write(MyClass.publicStaticVariable + 1 + '<br>'); } MyClass.publicStaticVariable = 20; // A public class variable MyClass.publicStaticMethod= function() { // A public class method document.write(this.publicVariable + 2 + ' '); document.write(MyClass.publicVariable + 2 + ' '); document.write(this.publicStaticVariable + 2 + ' '); document.write(MyClass.publicStaticVariable + 2 + '<br>'); } // Test: var myclass= new MyClass(); document.write(myclass.publicVariable + '<br>'); // 10 document.write(MyClass.publicVariable + '<br>'); // undefined myclass.publicMethod(); // 11 NaN NaN 21 //MyClass.publicMethod(); // error! document.write(myclass.publicStaticVariable + '<br>'); // undefined document.write(MyClass.publicStaticVariable + '<br>'); // 20 //myclass.publicStaticMethod(); // error! MyClass.publicStaticMethod(); // NaN NaN 22 22
Private methods are possible as inline constructor functions:
function MyClass() { // The constructor var privateVariable= 10; // A private instance variable var privMeth1= function {...} // A private method fuction privMeth2 {...} // private method (shortcut) var that= this; // To make this available for priv methods }
Notes:
this
seems only to be accessible in private methods by the that
workaround variable aboveprototype
-way doesn't seem to have access to private mehtods. You need privileged methods (see above) for that.Sources & more information:
see JS Guide 1.5 and dynWidget.js
const
is mentioned in the Mozilla guide but dosen't work with Rhino version and probabaly neither with IE
/** conchange event handler function */ function getNameAndValueOfInputField(event) { var name, value; if (event) { name = event.target.name; value = event.target.value; } else { // IE specific code. I hate it! name = window.event.srcElement.name; value = window.event.srcElement.value; } return {"name":name, "value":value}; } // set conchange event for input field: var input = document.getElementById("franz"): input.onchange = getNameAndValueOfInputField;
Event handler for value input fields
From MDC
A closure is a special kind of object that combines two things: a function, and the environment in which that function was created. The environment consists of any local variables that were in-scope at the time that the closure was created. Consequently, you can use a closure anywhere that you might normally use an object with only a single method.
Instead of
function Statusbar(elementId) { /* class constructor */ this.target = document.getElementById(elementId); this.setText = function(text) { this.target.innerHTML= text; } } var statusbar = new Statusbar("statusbar"); statusbar.setText("some text");
you can use:
function makeStatusTextSetter(elementId) { /* closure factory */ var target= document.getElementById(elementId); return function(text) { target.innerHTML= text; } } var setStatusText= makeStatusTextSetter("statusbar"); setStatusText("some text");
Imho mainly as callbacks for events:
<html><head> <script type="text/javascript" src="copy.js"></script> </head><body> <form id="form" action="dummy"> <textarea id="inbox" name="inbox" cols="80" rows="10"></textarea> </form> <pre id="outbox">...</pre> </body></html>
function makeCopyFkt(inboxNode, outboxNode) { /* inner funct is a closure witch gets attached the environment (including passed arguments) of the outer function */ return function () { outboxNode.innerHTML= inboxNode.value; } } window.onload = function() { /* called when html is loaded completely */ var inboxNode = document.getElementById('inbox'); var outboxNode = document.getElementById('outbox'); var copyFkt= makeCopyFkt(inboxNode, outboxNode); inboxNode.onblur= copyFkt; };
Global functions, i.e. functions which are defined outside of a class can easily be used as event callbacks for DOM nodes, but what about class member methods?
The following example will not work, because the callback function copy
has no access to this
at the time being called:
function Copier(inboxNode, outboxNode) { this.inboxNode = inboxNode; this.outboxNode = outboxNode; this.copy = function () { this.outboxNode.innerHTML= this.inboxNode.value; } } window.onload = function() { /* called when html is loaded completely */ var inboxNode = document.getElementById('inbox'); var outboxNode = document.getElementById('outbox'); var copier= new Copier(inboxNode, outboxNode); inboxNode.onblur= copier.copy; };
But it works with the closure way:
function Copier(inboxNode, outboxNode) { this.inboxNode = inboxNode; this.outboxNode = outboxNode; this.copy = function () { self.outboxNode.innerHTML= self.inboxNode.value; } var self= this; // reference to this is saved in environment for closures }
Or even shorter:
function Copier(inboxNode, outboxNode) { this.copy = function () { outboxNode.innerHTML= inboxNode.value; } }
But the best solution is imho to leave the class clean and pass the DOM node not directly the member function but an additional (anonymous) wrapper function as closure. This works also with real (prototype) methods:
function Copier(inboxNode, outboxNode) { this.inboxNode = inboxNode; this.outboxNode = outboxNode; } Copier.prototype.copy= function() {this.outboxNode.innerHTML= this.inboxNode.value;}; window.onload = function() { /* called when html is loaded completely */ var inboxNode = document.getElementById('inbox'); var outboxNode = document.getElementById('outbox'); var copier= new Copier(inboxNode, outboxNode); inboxNode.onblur= function() { copier.copy(); }; // <== "wrapper" closure };
Take care if you want to initialize more than on DOM callback in a loop. For this a callback factory function is necessary. See JavaScript Guide
Check out Emulating private methods with closures
Basic principles from Mastering Ajax series at IBM developerWorks - Simple AJAX Code-Kit - Raw cross browser code
To convert any javscript value to a JSON string, use json2.js at json.org
Code for writing and reading cookies by javascript is available here. An example can be found in my plainGTD App. Note that cookies can be manipulated easier by server side scripting, eg PHP
See Dojo Toolkit