JavaScript

Some notes and small examples about JavaScript. If you are looking for a proper tutorial, hopefully you will at least find a link here to help you. I also like the JavaScript book from Stefan Koch but it's in German, only. It is called "JavaScript: Einführung, Programmierung und Referenz inklusive Ajax".

Links und Sources

JavaScript Links

Version History

History of JavaScript Today most of JavaScript is described in the ECMAScript Standard.

BrowserJavaScript Version
Firefox 1.5JavaScript 1.6
Firefox 1.8JavaScript 1.8
InternetExplorer 6.0Jscript 5.6
InternetExplorer 7.0Jscript 5.7
InternetExplorer 8.0Jscript 6.0
ChromeJavaScript 1.6

Preface

Strict mode

The Strict mode ensures for example that you no longer can use undeclared variables

"use strict";
// var x;
x=42; // error!

Good JavaScript Code

JavaScript conventions

JavaScript conventions

  • use 4 spaces for indentation
  • end a simple statement with a semicolon
  • do not end a complex statement with a semicolon
  • put the opening bracket at the end of the first line
  • variable and function names written as camelCase
  • global variables and constants written in UPPERCASE
  • don't start names with a $ sign as it is often used in JavaScript library names

JavaScript best practice

JavaScript best practice

  • use strict
  • declare local variables with var
  • initialize them
  • declarations on top of file / function
  • avoid new Number/String/Boolean
  • use === instead of == (faster)
  • check if arguments are undefined an provide a default value for that case
  • end switch with default statement

JavaScript mistakes

JavaScript mistakes

  • Use = and not == (or ===) in comparisons
if(x=10)

is 10 which is always true

  • switch compares internally with === not with ==
  • avoid adding an extra "," after the last entry in an array or object definition as in x=[1,2,3,]
  • if you need to test for undefined / null do it like this
if (typeof myObj !== "undefined" ¨¨ myObj !== null)
  • if you leave a code block variables are still available and filled!

JavaScript performance

JavaScript performance

  • avoid using the "with" keyword
  • avoid statements in loops, because they will be calculated in each loop
for (i = 0; i < myArray.length; i++) {

instead use

le = myArray.length;
for (i = 0; i < le; i++) {
  • don't create unnecessary variables if you want to save their values.
a="a";
b="b";
x=a+b;

instead

x="a"+"b";

JavaScript Reserved Words

JavaScript Reserved Words

Data types

var u;                                // undefined
var x = null;
var n = 42;                           // Number
var d=34.00;                          // Number
var e=123e4;                          // Number
var s = "John Doe";                   // String
var a = ["John", "Doe", "Jane"];      // Array
var o = {id:42, name:"John", age:55}; // Object
var i =  2 / 0;                       // Infinity
var nan= 100 / "Foo";                 // Not a number
isNan(nan + 7);

typeof s; // string

Data types in JavaScript are dynamic

var x=42;
x=x+5;
x=x+"John"
x=2+3+"John"+7+3; // "5John73"
Number.MAX_VALUE;
Number.MIN_VALUE;
Number.NEGATIVE_INFINITY;
Number.POSITIVE_INFINITY;
Number.NaN;

Math

JavaScript Math

Date

Date

new Date(year, month, day, hours, minutes, seconds, milliseconds)

Create the date object for the 12.2.2010. Watch out, the month starts with 0, not with 1!

var d=new Date(2010, 1, 12);
Do not useDate.getYear() because depending of the Browser you might get the year with 2 or 4 digits. Use <pre>Date.getFullYear();</pre> (always 4 digits).
 

Operators

var k="abc";
var j=new String("abc");  // avoid this
var z=new String("abc");  // avoid this

(k==j)   // true, same value
(k===j) // false, different type (string vs object)
(j==z)  // false, objects cannot be compared

Boolean(1 >2)  // True
(1>2)          // True
("2"<"12")     // false, String comparison, 2 comes after 1 in alphabet

&uml;&uml; // and
|| // or

Strings

Have several methods and also properties

var s="abc";
s.charAt(1);
s.length
s.substr(start, end)
s.substring(start, length)
s.search("bc");

If

if (condition1) {
    ...

} else if (condition2) {
    ...

} else {
    ...
}

Switch

switch (new Date().getDay()) {
    case 0:
        day = "Sunday";
        break;
    case 1:
        day = "Monday";
        break;
    case 2:
        day = "Tuesday";
        break;
    case 3:
        day = "Wednesday";
        break;
    case 4:
        day = "Thursday";
        break;
    case 5:
        day = "Friday";
        break;
    case 6:
        day = "Saturday";
        break;
   default:
       day= "Unexpected";
}

Switch compares interally with === not with == so 10 and "10" do NOT match!

For

for (i = 0; i < x.length; i++) {
   x[i];
}

For in

var person = {fname:"John", lname:"Doe", age:42};
var x;
for (x in person) {
    ...
}

While

while (i < 42) {
    i++;
}

Do While

i=0;
do {
       i++;
} while (i < 42);

With break and continue, which may also use labels.

Throw, try and Catch

JavaScript Errors - Throw and Try to Catch

try {
    ...
}
catch(err) {
    ...
}
finally {
    ...
}

Include JavaScript

Include JavaScript in a way that it will not cause troubles for Browsers not being able to execute JavaScript:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
    <head>
      <title>JavaScript Demo</title>
    </head>
  <body>

   <div>
    HTML.

   <script type="text/javascript">
    <!--
    alert("JavaScript 4*3="+(4*3));
    // -->
   </script>
   <noscript>
    No Script
   </noscript>

  </body>
 </html>

It is preferable to put it in its own file and import it

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
    <head>
      <title>JavaScript Demo</title>
    </head>
  <body>

   <script type="text/javascript" src="myJavaScriptFile.js" />
   <noscript>
    JavaScript is not supported in your browser.
   </noscript>

  </body>
 </html>

Functions

Parameters in functions are Call by Value for base types and Call by Reference for objects. If you need Call by Reference you need to put the base types into objects. It is possible to have functions with a dynamic number of parameters

    function myConcat()
    {
     var result="";
     for (var i=0; i<myConcat.arguments.length; i++)
     {
      result+=myConcat.arguments[i];
     }
     return result;
    }

   // ab
   alert(myConcat('a', 'b'));

   // Hallo Welt
   alert(myConcat('Hallo', ' ', 'Welt'));

Scope

var a=1;  // global, can be read within f

function f() {
    var b=2; // local, only within f
    c=3;     // c has never been declared, is automtically GLOBAL!
}

For global variables var is optional. Within a function you need to use var or the variable will be global. If you use in a function let instead of var, a global variable with the same name will not be overwritten.

You should always use let or const instead of var beacause than the variables will only exist in the block scope. If you use const the variable can only be assigned once and not changed again (final in Java)

const a = 5;
var b=6;
b=7;
a=8; // not allowed

String to int

If you convert a String to Int always use the number system:

var i=parseInt("09", 10);

Array

JavaScript Arrays

Join, sort, and your own Comperator

function myReverseComperator(a, b)
{
 if(a>b) return -1;
 if(a<b) return +1;
 return 0;
}

var myArray = new Array();
myArray[0] = "Foo";
myArray[1] = "Bar";
myArray[2] = "Dog";
myArray[myArray.length] = "Cat";

myArray.sort();
// Bar - Cat - Dog - Foo
alert(myArray.join(" - "));

//myArray.reverse();
myArray.sort(myReverseComperator);
// Foo; Dog; Cat; Bar
alert(myArray.join("; "));

Associative Arrays do not really exist in JavaScript, they are objects, which might surprise you

var person = [];
person["firstName"] = "John";
person["lastName"] = "Doe";

person.length;   // 0 no array

Set

There was no Set in JavaScript but Objects might be used to simulate that

var mySet = {};

key='JohnDoe';

if (!(key in set)) {
  mySet[key] = true;
}

Objects

Objects only

var person = {
    firstName:"John",
    lastName:"Doe",
    age:50,
    eyeColor:"brown"
};

Access objects attributes

person.age;
person["age"];

Instead of copying values like that from an object

const a=Foo.a;
const b=Foo.b;

You can also do this

const { a, b } = Foo;

Methods in Objects

o.myMethod(); // calls the method
o.myMethod;   // get the method definition

Create Object with values and Getters and Setters

// note the , at the end of each line
var john = {
              name: "Doe",
              firstName: "John",
              get fullName() {
                     return this.firstName+" "+this.name;
              },
              set fullName(fullName) {
                     name=fullName; firstName="";
                     return this;
              }
}

Once you access the attribute the getters jumps in automatically

john.fullName; // John Doe via Getter

Class via Prototyping

Define Class via a prototype. First define a function, it will be the Constructor of your Class. It may contain other functions (becoming the member methods) or variables (becoming the member attributes)

//Class via Constructor
function TransportVehicle(pName) {

    this.name  =pName;   // public  member
    var _me;             // private member

    // manual getter / setter for public member
    this.getName = function() {
       console.log("getter Name called");
       return this.name;
    }

    this.setName=function(pName) {
        console.log("setter Name called with value " + pName);
        this.name=pName;
        return this;
   }

   // method defined within the constructor
   this.foo = function() {
       return "Foo";
   }
};

This is how you can create an object out of this class

var tv = new TransportVehicle("abc");

Before you do this, better think about defining the Getter and Setters like this, instead of doing them manually. This way you avoid the risk to bypass the Getters and Setters

// add implicit getters and setter via the prototype
TransportVehicle.prototype = {
    get price()      { console.log("getter Price called");                                        return this._price; },
    set price(price) { console.log("setter Price called with value " + price); this._price=price; return this;}
}
// Since ECMAScript 5: Add implicit getters and setters via the prototype
Object.defineProperty(TransportVehicle.prototype, "maxSpeed", {
    get: function() {return this._maxSpeed;},
    set: function(maxSpeed) {this._maxSpeed = maxSpeed; return this;}
});

Usage

tv.getName(); // name via getter
tv.name;      // name via public variable

tv.price=42;   // price via setter
tv.price;      // price via getter

// bmw.getPrice(); does not exit

tv.maxSpeed=203;            // via setter
tv.maxSpeed;                // via getter

// tv.getMaxSpeed(); does not exist

You may also add normal methods to your class outside the Constructor

//method defined outside the constructor via prototype
TransportVehicle.prototype.bar = function() {
   return "Bar";
}

Both will work the same way

tv.foo();
tv.bar();

Inheritance

Just define another function which will be your constructor. But this time set its prototype to an instance of the desired father class.

// Car is a TransportVehicle
function Car(pName, pNrOfWheels) {
    this.prototype=new TransportVehicle(pName);

    //also add getters and setters via the prototype
    Object.defineProperty(this, "nrOfWheels", {
        get: function()           { return this._nrOfWheels; },
        set: function(nrOfWheels) { this._nrOfWheels = nrOfWheels; return this; }
    });

   // use setter implicitly because setter was defined before us
   this.nrOfWheels=pNrOfWheels;    

}



// Overwrite method in Car
Car.prototype.foo=function() {
    // result from father class and change the result slightly
    return this.prototype.foo()+"ooooo";
}

var bmw=new Car("BMW 3", 4);
bmw.nrOfWheels; // via implicit getter
bmw.foo();      // Fooooooo

JavaScript Object Natation (JSON)

JavaScript Object Natation (JSON), eine Kurzschreibweise für JavaObjekte

var deposit= { currency:"EUR",
               value:"120,12",
               getString:function() { return this.value+"("+this.currency+")"; }
             }

Important Objects

ObjectsExample
windowz.B. window.alert();
documentAccess to the website
locationAccess on the URL of the current page

JavaScript, CSS, move objects

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
    <head>
      <title>JavaScript Demo</title>

      <style type="text/css">
        #d1 { color:red;  position:fixed; top:10px;  left:10px; }
        #d2 { color:blue; position:fixed; top:100px; left:100px; }
      </style>
    </head>
  <body>

   <div id="d1">Foo</div>
   <div id="d2">Bar</div>

   <script type="text/javascript">

    var o1=document.getElementById("d1")
    var o2=document.getElementById("d2")

    var myCounter=0;

    function moveIt()
    {
      o1.style.left=10+myCounter+'px';
      o2.innerHTML='Value: '+myCounter;
      myCounter++;
      if(myCounter>100) clearInterval(myInterval);
    }

    var myInterval=setInterval("moveIt()", 20);

   </script>

  </body>
 </html>

DOM

Firefox DOM Inspector

DOM Level 0

There are arrays for some objects (e.g. for links and pictures). For example

document.links[i];

DOM Level 2

For all objects in an HTML page there is an object.

<div id="d1">
 First
 <div id="d2">
  Second
  <ul id="d3">
   <li>A</li><li>B</li>
   <li>C</li>
  </ul>
 </div>
 <span id="d4"><a href="http://www.example.com">third</a></span>
</div>

<hr />

<div id="result">Result:</div>

<script type="text/javascript">
 var o1=document.getElementById("d1");
 var o2=document.getElementById("d2");
 var o3=document.getElementById("d3");
 var o4=document.getElementById("d4");

 var result=document.getElementById("result").childNodes[0];

 // First
 result.nodeValue+=" "+o1.childNodes[0].nodeValue;

 // Second
 result.nodeValue+=" "+o2.childNodes[0].nodeValue;

 // ul
 for(var i=0; i<o3.childNodes.length; i++)
 {
   if("object"===typeof o3.childNodes[i].childNodes[0])
   {
        result.nodeValue+=i+": "+o3.childNodes[i].childNodes[0].nodeValue+" ";
   }
 }

 // a href
 var ol=o4.childNodes[0];
 result.nodeValue+=ol.childNodes[0].nodeValue;
 result.nodeValue+=" -> "+ol.getAttribute('href')

 // other possibility
 result.nodeValue+="; "+o3.innerHTML;
</script>

Events

List of important events, see also DOM Events

  • onchange
  • onclick
  • onfocus
  • onload
  • onmouseon
  • onmouseover
  • onload

W3C Event Listener / IE Event Listener

W3C Event-Listener (not supported by IE) and Micrsoft Internet Explorer events

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" lang="de" xml:lang="de">
    <head>
      <title>JavaScript Demo</title>

      <style type="text/css">
  .stylA { font-size:large;  color:red;  }
  .stylB { font-size:normal; color:green; }
      </style>

      <meta http-equiv="Content-Script-Type" content="text/javascript" />

    </head>
  <body>

   <div id="d1" class="stylB" onmouseover="this.className='stylA';" onmouseout="this.className='stylB';">
     Foo
   </div>

   <script type="text/javascript">

     var o=document.getElementById("d1");

     if("function"===typeof o.addEventListener)
      o.addEventListener("click", myFunction, false);
     else if("function"===typeof o.attachEvent)
      o.attachEvent("click", myFunctionIE);

     function myFunction(pEvent)
     {
      o.childNodes[0].nodeValue+=".("+pEvent.clientX+"/"+pEvent.clientY+")";
     }

     function myFunctionIE()
     {
      o.childNodes[0].nodeValue+=".("+window.event.offsetX+"/"+window.event.offsetY+")";
     }

   </script>

  </body>
 </html>

Pass and read parameters

var myNewURL="foo.bar?"+encodeURIComponent("Hello World!");
alert(myNewURL);

var myParams=location.search;
myParams=myParams.substring(1, myParams.length);
myParams=decodeURIComponent(myParams);
alert(myParams);

Links you can bookmark

location.hash can be used to make it possible to set a bookmark for state of a dynamic site.

Examples

Size of an element should grow

An input element for texts should grow while the text enlarges or shrinks.

The code can be placed directly at the element

<input type="text"  ... size="2" onkeyup="var newsize=this.value.length; if(newsize<2) { newsize=2; }; if(newsize>1000) { newsize=1000; }; this.setAttribute('size', newsize);" />

or put it into its own method

<script type="text/javascript">
<!--
/* this function can be used to enlarge text input
 * fields while the users enters text into it.
 * Usage: <input type="text" onkeyup="enlarge_size_with_value_length(this);" ...
 */

function enlarge_size_with_value_length(o)
{
 var minsize=2;
 var maxsize=1023;
 var newsize=o.value.length;
 if(newsize<minsize) {
   newsize=minsize;
 };
 if(newsize>maxsize) {
   newsize=maxsize;
 };
 o.setAttribute('size', newsize);
};
//-->
</script>


<input type="text"  ... size="2" onkeyup="enlarge_size_with_value_length(this)"

Ajax

Asynchronous JavaScript and XML

// get XMLHttpRequest object for most browsers
function getXMLHttpRequest()
{
 if(window.XMLHttpRequest) return new XMLHttpRequest();
 if(typeof ActoveXObject!="undefined") return new ActiveXObject("Microsoft.XMLHTTP");
 return null;
}

talk2me=getXMLHttpRequest();

talk2me.onreadystatechange=gotOne;
talk2me.open("get", "data1.xml", true);
talk2me.send(null);

function gotOne()
{
 if(talk2me.readyState==4)
 {
  if(talk2me.status==200)
  {
   alert(talk2me.responseText);
  }
 }
}

Ask the browser where we are on exactly on earth

if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, onError); //
also monitor position as it changes
navigator.geolocation.watchPosition(showPosition); } else { onError();
}

function showPosition(position)
{
 ...
}

function onError()
{
  if (navigator.geolocation)
  {
    // Error in geolocation service
  }
  else
  {
    // Warning: Browser does not support geolocation
  }
}

Misc