<< Click to Display Table of Contents >> Navigation: 11. Appendix > 11.1. Appendix A: Introduction to the Standard JavaScript Language |
This section presents a brief introduction to the JavaScript language so that you can understand the code snippets presented in the rest of the guide (mainly in section 6), so that you can start writing your own scripts.
Inside Anatella, you can write new Actions using Javascript (and also R, Python or C/C++). The “official” name of the JavaScript-language used in Anatella is ECMAScript, the standardized version of JavaScript. ECMAScript forms the basis of JavaScript (Mozilla), JScript (Microsoft), and ActionScript (Adobe). Although the language's syntax is superficially similar to C++ and Java, the underlying concepts are somewhat different.
We will now quickly review the fundamental of the JavaScript language. A summary of all standard functionalities offered by any JavaScript/ECMAScript compliant language is given in appendix E. The special extentions of Javascript provided by Anatella are listed in appendix F.
The Mozilla Foundation's web site hosts a more complete tutorial at http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide, and David Flanagan's “JavaScript: The Definitive Guide (O'Reilly, 2006)” is recommended both as a tutorial and as a reference manual. The official JavaScript / ECMAScript specification is available online at http://www.ecmainternational.org/publications/standards/Ecma-262.htm.
The basic JavaScript control structures—if statements, for loops, and while loops—are the same as in C++ and Java. JavaScript also provides more or less the same assignment, relational, and arithmetic operators. JavaScript strings support concatenation with + and appending with +=.
To get a feel for the JavaScript syntax, we will start by a small example:
function square(x)
{
return x * x;
}
function sumOfSquares(array)
{
var result = 0;
for (var i = 0; i < array.length; ++i)
result += square(array[i]);
return result;
}
var array = new Array(100);
for (var i = 0; i < array.length; ++i)
array[i] = (i * 257) % 101;
print(sumOfSquares(array));
This will print “336234” in the console.
From a classical Java or C++ programmer's perspective, probably the most striking feature of JavaScript is that variables are not explicitly typed; the var keyword is all that is required to declare a variable. Read-only variables are declared with const instead of var. Another noteworthy feature of the preceding program is that there is no main() function. Instead, the code that is located outside any function is executed immediately, starting from the top of the file and working down to the bottom.
Unlike in Java or C++, semicolons at the end of statements are generally optional in JavaScript. Using sophisticated rules, the interpreter can insert most missing semicolons itself. Despite this, typing semicolons ourselves is recommended, to avoid unpleasant surprises.
If we don't provide an initial value when declaring a variable with var, the default value is undefined, a special value of type Undefined. We can later assign any value of any type to the variable using the assignment operator (=). Consider the following examples:
var x;
typeof x; // returns "undefined"
x = null;
typeof x; // returns "null"
x = true;
typeof x; // returns "boolean"
x = 5;
typeof x; // returns "number"
x = "Hello";
typeof x; // returns "string"
The typeof operator returns a lowercase string representation of the data type associated with the value stored in a variable. JavaScript defines five primitive data types: Undefined, Null, Boolean, Number, and String. The Undefined and Null types are special types for the undefined and null constants, respectively. The Boolean type consists of two values, true and false. The Number type stores floating-point numbers. The String type stores Unicode strings.
Variables can also store objects and functions, corresponding to the data types Object and Function. For example:
x = new Array(10);
typeof x; // returns "object"
x = print;
typeof x; // returns "function"
Like Java, JavaScript distinguishes between primitive data types and object types. Primitive data types behave like C++ value types, such as int and double. These are created without the new operator and are copied by value. In contrast, object types must be created using the new operator, and variables of these types store only a reference (a pointer) to the object. When allocating objects with new, we do not need to worry about releasing their memory, since the garbage collector does this automatically.
If we assign a value to a variable without declaring it first using the “var” keyword, the variable will be created as a global variable. And if we try to read the value of a variable that doesn't exist, we get a ReferenceError exception. We can catch the exception using a try ... catch statement, as follows:
try {
print(y);
} catch (e) {
print(e.name + ": " + e.message);
}
If the variable “y” does not exist, the message "ReferenceError: y is not defined" is printed on the console.
If undefined variables can cause havoc in our programs, so can variables that are defined but that hold the undefined constant—the default value if no initializer is provided when declaring a variable using var. To test for undefined, we can use the strict comparison operators === or !==. For example:
var x;
...
var y = 0;
if (x !== undefined)
y = x;
The familiar == and != comparison operators are also available in ECMAScript, but unlike === and !==, they sometimes return true when the compared values have different types. For example, 24 == "24" and null == undefined return true, whereas 24 === "24" and null === undefined return false.
Let’s go back to our first example. This first program illustrates how to define our own functions in JavaScript:
function square(x)
{
return x * x;
}
function sumOfSquares(array)
{
var result = 0;
for (var i = 0; i < array.length; ++i)
result += square(array[i]);
return result;
}
var array = new Array(100);
for (var i = 0; i < array.length; ++i)
array[i] = (i * 257) % 101;
print(sumOfSquares(array));
Functions are defined using the “function” keyword. In keeping with JavaScript's dynamic nature, the parameters are declared with no type, and the function has no explicit return type.
By looking at the code, we can guess that the “square()” function should be called with a Number and that the “sumOfSquares()” function should be called with an Array object, but this doesn't have to be the case. For example, square("7") will return 49, because JavaScript’s multiplication operator will convert strings to numbers in a numeric context.
Similarly, the sumOfSquare() function will work not only for Array objects but also for other objects that have a similar interface.
In general, JavaScript applies the duck typing principle: "If it walks like a duck and quacks like a duck, it must be a duck". This stands in contrast to the strong typing used by C++ and Java, where parameter types must be declared and arguments must match the declared types.
Instead of defining an array variable, we can pass an array literal:
print(sumOfSquares ([4, 8, 11, 15]));
JavaScript lets us supply more arguments to a function than there are parameters declared. The extra arguments are accessible through the arguments array. Consider the following example:
function sum()
{
var result = 0;
for (var i = 0; i < arguments.length; ++i)
result += arguments[i];
return result;
}
print(sum(1, 2, 3, 4, 5, 6));
Here, the sum() function is defined to take a variable number of arguments. The arguments are the numbers that we want to sum.
The arguments array can be used to overload the behavior of functions based on the types of the arguments or on their number.
More information about advanced features of Javascript is given in the next appendix (Appendix B). A summary of all standard functionalities offered by any JavaScript / ECMAScript compliant language is given in appendix E. The special extentions of Javascript provided by Anatella are listed in appendix F.