Benutzer-Werkzeuge

Webseiten-Werkzeuge


becki:linux:javascript

Javascript

Variables

var Keyword

Within functions always prefix variables with var, otherwise they become global! See Avoid Global namespace

Strings

A string can be an instance of the String class or a string literal. More

String Literals

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.

Creating Strings

var s1 = "foo";             //creates a string literal value  
var s2 = new String("foo"); //creates a String object  

More

String Concatenation

var a= "al" + "pha" // a == "alpha"
a   += "bet"        // a = "alphabet"

String Comparison

FIXME Because Strings are ojects, String comparison is the same as object comparison :?:

String Methods/Property

String length: var len = mystring.length;

All string methods

Arrays

An Array is an instance of the Array class. More

Creating Arrays

var arr= new Array(element0, element1, ..., elementN);
var arr= [element0, element1, ..., elementN];
 
var arr= new Array(arrayLength);
var arr= [];

Array Methods/Property

Array length: var len = myarray.length;

Array Methods

Objects and Inheritance

Object creation

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());

FIXME

  • This variant is to be verified
  • Does this cause overhead?
  • What about inheritance?

Object literals

FIXME

Object cloning

Objects are passed by refernce

> Something like a copy constructor is necessary:

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)

Object Comparison

FIXME

Defining Methods

Method definition inline inside of the constuctor

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

  • its not easy to see to which object the method definitions belong to
  • method definitions could be called directly whitout existing 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 :-)

Public Access

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

Public Access

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:

  • Private methods possibly cause overhead, compared to the prototype way of public methods
  • this seems only to be accessible in private methods by the that workaround variable above
  • Public methods defined with the (recommended) prototype-way doesn't seem to have access to private mehtods. You need privileged methods (see above) for that.

Sources & more information:

Inheritance

FIXME see JS Guide 1.5 and dynWidget.js

Misc

Constants

const is mentioned in the Mozilla guide but dosen't work with Rhino version :?: and probabaly neither with IE

Events

For event handling see: Mozilla & Selfhtml

See also Dojo events

Get the Source of the Event

/** 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

Closures

From MDC

Principle

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");

Practical Usage

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;
};

Using class member methods as event callbacks

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

FIXME Check out Emulating private methods with closures

Ajax

Links

Sending JSON to Server

To convert any javscript value to a JSON string, use json2.js at json.org

Todo / Pending

Cookies

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

Dojo Toolkit

Using Javascript from the Command Line

Cookies helfen bei der Bereitstellung von Inhalten. Diese Website verwendet Cookies. Mit der Nutzung der Website erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Computer gespeichert werden. Außerdem bestätigen Sie, dass Sie unsere Datenschutzerklärung gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website. Weitere Information
becki/linux/javascript.txt · Zuletzt geändert: 2011-03-21 17:04 von becki

Impressum - Datenschutzerklärung