Dies ist eine alte Version des Dokuments!
Within functions always prefix variables with var
, otherwise they become global! See Avoid Global namespace
function MyClass() { // constructor this.method1= function(arg) {/* code */}; // method }
Seems to cause overhead, see http://phrogz.net/JS/Classes/OOPinJS.html
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 seem to be only possible as inline constructor functions, but those seem to cause overhead.
The classic Java-like way:
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());
The closure way: (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 whit 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)
see JS Guide 1.5 and dynWidget.js
/** 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
For event handling see: Mozilla & Micro$oft
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
To convert any javscript value to a JSON string, use json2.js at json.org
look in http://www.ibm.com/developerworks/views/web/libraryview.jsp?search_by=Mastering+Ajax
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
Quick start, Tutorial, Reference, Feature explorer (incomplete?), hello world (outdated) Dojo Lib from AOL's CDN