Javascript is a loosely typed language with objects as containers and prototypal (not classical) inheritance. It support lambda functions. Except in name, Javascript has nothing to do with Java.
Don't forget about JSLint, Douglas Crockford's Javascript code quality tool.
Link to external Javascript file from HTML doc:
<script src="script.js"></script>
Note that it is not necessary to specify type="application/javascript" in the script tag, because most browsers will ignore it and trust the MIME type supplied by the webserver instead.
Inline Javascript:
<script>
<!--
my script
-->
</script>
Note that if you load multiple scripts, they all share one global namespace. Watch out for name collisions.
Locate scripts as close to the closing body tag as possible (i.e.—at the end of the document, not inside the head section as is commonly done.
This is test.html:
<html><body><p> <script src="test.js"></script> </p></body></html>
This is test.js:
document.write('Hello, world!');
Javascript's built-in types are: Numbers, String, Booleans, Objects, null, and undefined.
Numbers are internally 64-bit floating point, so if you're dealing with dollar amounts turn the values into cents by multiplying by 100 before doing arithmetic. Javascript has a number of potentially useful built-in math functions: abs, floor (rounds down to nearest integer), log, max, pow, random, round, sin, and sqrt.
Strings are immutable. They can be compared with the == operator. Javascript doesn't care if you enclose your strings in single or double quotes—they're functionally identical. Javascript provides the flowing string functions: charAt, concat, indexOf, lastIndexOf, match, replace, search, slice, split, substring, toLowerCase, and toUpperCase.
The Boolean values in Javascript are true and false. There is a boolean function which returns true or false according to the value of the argument: Boolean(value). The values false, null, undefined, "" (empty string), 0, and NaN all evaluate as false. All other values evaluate as true.
Javascript also has arrays (but be warned that, for most proposes, Javascript's arrays are terribly inefficient). Arrays inherit a number of methods, including: concat, join, pop, push, slice, sort, and splice.
Also see extending built-in types.
Apart from the above types, everything in Javascript is an object.
/****************************************************************************
Comments
****************************************************************************/
// Single line comment
/* Multi-
line
comment */
/****************************************************************************
Variables
****************************************************************************/
var x; // Declare a variable
x = 5; // Assign a value to variable
var foo = "bar"; // Declare and initialize in one statement
foo = "nerf" + "baf"; // String concast operator is +
var nums = new Array( 3, 1, 4 ); // Arrays are provided by the Array class
// The bracket notation is preferred over new Arrary():
myArray = ['bats', 'rats', 'cats'];
myArray[myArray.length] = 'knats'; // Append to existing array
/* array.length is always 1 larger than highest array subscript. You can
iterate over arrays like: */
for (i = 0; i < myArray.length; i += 1) {
foo(myArray[i]);
}
/****************************************************************************
Loops and conditionals
****************************************************************************/
if ( foo == "bar" ) {
document.write( "<p>It's bar!<p>" );
} else if ( foo == "nerfbaf" ) {
document.write( "<p>It's nerfbaf!<p>" );
} else {
document.write( "<p>Dunno...<p>" );
}
for ( i = 0; i <= 100; i++ ) {
document.write("Who is number " + i + "?<br />");
// You are number two.
}
var i = 0;
while (i <= 10 ) {
document.write("Number: " + i + "?<br />");
i++;
}
do {
document.write("Number: " + i + "?<br />");
i++;
} while ( i <= 10 );
switch ( n ) {
case 0: // Case values can be a number, string, or expression.
obliterate( noone );
break;
case 1:
obliterate( everyone );
break;
default:
playagain();
}
// Javascript has labeled breaks:
myLoop: for (;;) {
...
if (...) {
break myLoop;
}
...
}
/****************************************************************************
Functions
****************************************************************************/
function foo ( parameter ) {
return parameter + parameter;
}
/* If you don't explicitly return a value from a function, the value
undefined is returned. (The exception to that is constructors,
which return the new object this.) */
Most C operators (+ - * / % == != < > >= <= && || ! & | ^ >> >>> << ?:) work as expected with a few exceptions. The + operator is overloaded; it does arithmetical addition on numbers, and concatenation on strings. The == and != operators do type coercion (so that "42" == 42 is true); the === and !== operators do NOT do type coercion (so "42" === 42 is false).
The && operator is just messed up. If the first operand is true, && returns the second operand. Otherwise, && returns the first operand. The || works the opposite way. If the first operand of || is true, it returns that first operand. Othersise, || returns the second operand.
Variable scope is a little annoying in Javascript. Functions have a scope (variable are local to that function), but braced blocks do not have a scope (variables are global). Every object has its own namespace. One of the common Javascript patterns is to protect your namespaces inside functions. I have seen several methods for doing so. This one makes sense to me:
if (!org) var org = {};
if (!org.paulgorman) org.paulgorman = {};
org.paulgorman.myscript = function () {
var pub = {}; // For public and private scopes.
pub.color = 'Blue';
pub.addNumbers = function (a,b) {
return a + b;
}
return pub;
} ();
Javascript doesn't have classes. You can make a new object (or type of object) simply by listing its components. (This is how JSON works.) A Javascript object is simply an unordered collection of name/value pairs. The names are strings, but the values can be anything, including other objects.
If you attempt to apply classical design patterns directly to JavaScript, you will be frustated. But if you learn to work with JavaScript's prototypal nature, your efforts will be rewarded. —Douglas Crockford.
Inheritance in Javascript means that a new object inherits from an existing prototype object, not a class. Every Javascript object has a secret link to a parent object from which it inherits properties.
Javascript doesn't have classes, methods, constructors, or modules. Functions do the work of all of those.
Javascript's functions are first class objects, and in that respect Javascript shares more with lambda languages like Lisp than C. Javascript functions can be passed as arguments, returned, and stored in variables. Functions inherit from Object, and can store name/value pairs or even other functions. A function can be used anywhere an expression can be used.
Inner functions can be declared inside other functions, and those inner functions have access to the variables and parameters of the functions in which they're contained. An inner function can access the values of its outer function even after the outer function has returned. (This is called closure.)
A function inside an object is called a method. There are four ways to call methods, each of which has slightly different uses:
object.method(arguments), it gets an extra, implicit argument called this, which refers to the object containing the function.functionObject(arguments), the this argument points to the global object, which usally isn't very useful. If you're writing a helper function inside an object, you may want to pass it the reference to its parent object by first setting var that = this, so you can pass that to the helper function.new functionObject(arguments). When a function in invoked using the constructor form, a new function object is created, and the this argument refers to that new function object. If the new function object does not explicitly specify some other return value, then it implicitly returns this.functionObject.apply(thisObject, [arguments])// Douglas Crockford recommends this function to ease object creation:
if (typeof Object.create !== 'function') {
Object.create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
myNewObject = Object.create(oldObject);
// Member names can be written as bare names or quoted strings.
var myObject = {name: "Frank", "color": "red"};
// Use either of two notations to access object memebers:
var myName = myObject.name;
var myName = myObject[name];
// Iterate through object members:
for (var member in object) {
// if avoids iterating through members of parent objects (annoyance):
if (object.hasOwnProperty(member)) {
foo(object[member]);
}
}
// Objects are mutable. New members can be added anytime:
myObject.god = "Zeus";
// A new object inheriting from an existing object:
var newObject = object(myObject);
/* The object() function creates a behind-the-scenes link from the new object
to the old object. */
// Note that doStuff() function gets a reference to myObject as this:
myObject.doStuff(42);
// Functions automatically get an array-like variable called arguments:
function sum() {
var i, n = arguments.length, total = 0;
for (i =0; i < n; i += 1) {
total += arguments[i];
}
}
You can extend any of Javascript's built-in types by assigning to Object.prototype, Array.prototype, Function.prototype, Number.prototype, String.prototype, or Boolean.prototype:
String.prototype.trim = function () {
return this.replace( /^\s(\S*(\s+\S+)*)\s*$/, "$1");
};
You can make up your own exception types, but Javascript comes with these built-in exceptions: Error, EvalError, RangeError, SyntaxError, TypeError, and URIError.
// Throw an exception like this:
throw new Error(errorMessage);
// Or throw an exception like this:
throw {
name: myException,
message: errorMessage
};
// Try to catch exceptions:
try {
foo();
} catch (e) {
switch (e.name) {
case 'Error':
...
break;
default:
throw e;
}
} finally {
blerg();
}
The contents of HTML pages are represented in the browser as a tree-like structure called the document object model. Elements in the tree can have children and siblings. There are three built-in functions to get elements form the DOM: document.getElementById(id), document.getElementsByName(name), and document.getElementsByTagName(tag).
Notice that there is no built-in way to get a node by its class. Crockford presents the following function which transverses the DOM:
function walkTheDOM(node, func) {
func(node);
node = node.firstChild;
while (node) {
walkTheDOM(node, func);
node = node.nextSibling;
}
}
Walking the DOM could be used, to get all the nodes of a particular class:
function getElementsByClassName(className) {
var results = [];
walkTheDOM(document.body, function (node) {
var a, c = node.classname, i;
if (c) {
a = c.split(' ');
for (i = 0; i < a. length; i += 1) {
if (a[i] === className) {
results.push(node);
break;
}
}
}
});
return results;
}
Reading and writing elements of the DOM can be done with node.getAttribute('src') and node.setAttribute('src', newurl).
Douglas Crockford uses the following handy functions in his videos and books:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
}
if (typeof Object.create !== 'function') {
Object.create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
myNewObject = Object.create(oldObject);
© Paul Gorman