JavaScript

From Knowino
Revision as of 07:44, 13 June 2013 by Paul Wormer (talk | contributions)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

JavaScript is a computer language with a name licensed to Oracle®. JavaScript (JS) is a scripting language and as such it has fewer capabilities than full-fledged computer languages like C, Java, or C++. Its name seems to imply that it is a scripting variant of the computer language Java, which it is not, although the JS syntax (loops, Boolean expressions, etc.) is reminiscent of Java.

JavaScript programs are usually embedded in a host environment, such as Web browsers or Windows Script Host. The embedded version of the language is known as client-side JS.[1] Client-side JS has no built-in support for reading or writing files, such actions must be performed by the host. Being present in all Web browsers of today (2012), JavaScript is probably used more than any other programming language in the world.

Brendan Eich designed the language for one of the early Web browsers, Netscape Navigator, and gave it the name LiveScript. LiveScript was part of Netscape Navigator 2.0, released in September 1995. In an announcement of Netscape and Sun Microsystems dated December 4, 1995 the language was renamed to JavaScript; it is generally assumed that the name change was for marketing reasons. In June 1997 the European Computer Manufacturers Association (ECMA) published a standard for the language called ECMAScript-1 (for legal reasons it was not called JavaScript). In December 1999 ECMAScript-3 appeared, which is the most widely used version of the language. It is compatible with Netscape/Mozilla JavaScript v. 1.5 and Microsoft® JScript 5.5. In June 2011 the standard ECMAScript-5.1[2] appeared. The specification for ECMAScript-4 was never published.

JavaScript is loosely typed, which means that the data types of variables are not declared explicitly. One cannot assign a priori a variable to a number, a string, or any other of the data types allowed by JS.

The language is often described as object oriented, but it is better called prototype oriented, a concept that was pioneered in the programming language Self. A prototype is a property of a constructor function that can be created and changed dynamically (during execution of the script). The inheritance of properties of instances proceeds through the prototype properties of the constructors in the inheritance chain.

JS shares with functional languages, such as the Lisp dialect Scheme, the fact that functions are first class entities. This means that a function can be returned as parameter from another function and can be assigned to a variable. Also, a function can enter another function as argument. Furthermore, a function may be nested within another function (its "host") and the nested function has access to the variables (lexical environment) of its host. Often such access takes place after the host has returned the nested function (which is assigned to a variable) and finished execution. When the nested function is later invoked it still has read/write access to the variables in its lexical environment. This so-called closure of the nested function over its lexical environment, which originated in Scheme, is typical for modern functional programming languages. JavaScript's closure and prototype inheritance are features that are not found in older imperative computer programming languages such as C or Fortran.

Contents

[edit] Small JavaScript example for use in a web browser

Writing a line to a web page written in HTML (hypertext markup language) is done by invoking the method write of the object document. Thus, the JS statement document.write("Hello, world") can be used to write the string   Hello, world   to the screen. However, first the web browser must be told that one or more lines of JS are appearing among the HTML lines. This is done by sandwiching the code between the HTML tags <script> and </script>. That is,

<script>
   document.write("Hello, world");
</script>

appends the string   Hello, world   to the web page written before the tag <script>.

JavaScript has a constructor Date. This constructor creates an object that contains the current date and time. Date offers many methods to format the current date. One of them is the method toLocaleDateString(), which returns a string containing the date according to local conventions (local means the country where the computer, doing the browsing, is registered). In the Netherlands:

<script>
   var dateNow = new Date();
   document.write(dateNow.toLocaleDateString());
</script>

writes something like maandag 24 oktober 2011. (Or whatever the actual weekday/month is). The new statement creates the new object dateNow that inherits the method toLocaleDateString() from its constructor. The output of the method is a string containing the current weekday followed by day, month, and year. As is common in object-oriented programming languages, the method is invoked as suffix of the object separated by a dot: obj.mthod() is the statement that lets mthod() act on obj.

[edit] Summary of JavaScript's characteristics

The most noticeable properties of the programming language JavaScript are:

Syntax
JS's syntax is close to that of Java.
Imperative language
JS has the same command repertoire as imperative languages like C (assignments, functions, loops, logical statements).
Objects
JS supports objects. Objects can be accessed as associative arrays (string in square brackets) or by object notation (suffix separated by period).
Arrays
JS supports arrays that are created dynamically. An array element can be any legitimate JavaScript object.
Prototype-based inheritance
JS's inheritance rules differ from object-oriented programming languages that employ class-based inheritance.
Functional programming
JS is a functional programming language; functions are first-class, i.e., ordinary objects. There is support of nested functions and closures. In ECMAScript-3 variables have function scope and not block scope.
Regular expressions
JS supports regular expressions that are to a large extent compatible with those of Perl.

In the next sections the properties of core JavaScript, listed above, will be exemplified. These sections do not contain an exhaustive description of JS, they give only the flavor of the language; see Ref.[3] for the complete language. Most lines in the examples below contain JavaScript comments—preceded by //. Values are printed to the screen by means of the method log of the object console. The values printed by console.log(.., ..) are usually given in a comment preceded by =>.

[edit] Imperative commands

[edit] Declaration

Variables local to functions are declared by var. Omitting a declaration makes a variable global (accessible from any function). In the var statement initial values may be assigned.

Example:
      var obj = {animal: "Monkey"}, pi = Math.PI, i =0; 
      console.log(obj.animal, pi, i) //=> Monkey 3.141592653589793 0

[edit] Functions

JavaScript knows functions that, as in all computer languages, perform specific well-defined tasks. JS functions do not have to return a value. If no value is returned explicitly, a function returns the default value undefined (a built-in primitive JavaScript value). The syntax of the JS function statement is

 
     function name(p1, p2, ...){ 
            zero or more JS statements
     } 

where p1, p2, ... are function parameters. Even if the function does not have parameters, a pair of matching parentheses is required. The function body (statements between curly brackets) can consist of any statements, including function statements. The function name is invoked by name(arg1, arg2, ..). If a value is to be returned, or if an early return to the calling subprogram is needed, the return statement can be used.

Example:
      function example(x){
         var obj = {animal: "Monkey"}, pi = Math.PI, i =0; 
         if (i !== x) return "Error";
         console.log(obj.animal, pi, i);
      } 
      console.log(example(0)) // => Monkey 3.141592653589793 0
                              // => undefined [return value of example(0)] 
      console.log(example(1)) // => Error

The function statement above is similar to the procedure definition present in all imperative languages. As a functional language, JS has also the possibility to assign a function expression to a variable (the right-hand side is the function expression, the left-hand side contains the name of a variable that is bound to a function):

var fnc = function(){ body };

Often the function in a function expression (also known as a function literal) is unnamed (an anonymous function). A function literal may have a name, which then is mainly used in recursive invocations of the function (JS allows recursive function calls).

[edit] Loops

JavaScript knows a for loop, a while loop and a do/while loop. In three examples the following sum will be computed:


 S_n := \sum_{i=0}^n i = n(n+1)/2

for n = 10, that is, S10 = 55.

1. The for loop has the schematic syntax:

for (initialization; test; increment) {loop body}.
Example:
      for (var sum=0, i=0;  i<=10;  i++){sum += i;} 
      console.log(sum)  // => 55

The statement sum += i is shorthand for sum = sum+i; i++ assigns i adds 1 to i and stores the updated i.

2. The while loop has the schematic syntax:

initialization; while (expression) {loop body}

where expression has the value true or false.

Example:
      var sum=0, i=0;
      while (i<=10) {sum += i++;} 
      console.log(sum)  // => 55

3. The do/while loop contains a "post check", the body of the loop is executed at least once. Schematic syntax:

do {loop body} while (expression)
Example:
      var sum=0, i=0;
      do {sum += i++;} while(i <= 10); 
      console.log(sum)  // => 55

[edit] Logical expression

The main form of the logical expression has the symbolic syntax:

if (expression) {statements;} else {statements;}

where expression must have value true or false. The statements can be any JS statements, including other logical expressions.

Example:
      var i=1, j=2, k=1;
      if (i !== j) {
          if (i == k) {
              console.log("i not equal j and i equal k") // this is written
          }
      }   
      else {
         console.log(" i  equal j")
      }

[edit] Objects

The easiest way to create an object in JavaScript is as a literal: {name1: value1, name2: value2, ...}, where value1, value2, ... can be any legitimate JavaScript entity, including an object or array.

[edit] Example

An object with three properties that have the respective values: a string, a mathematical constant, and another object is created.

   var obj = {s: "String", c: Math.PI, o: {s1: "Again", c1: 3.33}};
   for (var k in obj){console.log(k, obj[k])}

This prints:

   s String 
   c 3.141592653589793 
   o ({s1:"Again", c1:3.33}) 

In the loop k receives the consecutive property names of the object obj and the array-type access obj[k] gives the corresponding value. Alternatively one could use object (dot) notation to print the values of the three properties of obj:

   console.log(obj.s, obj.c, obj.o)

yielding:

   String 3.141592653589793 ({s1:"Again", c1:3.33}) 

[edit] Arrays

An array literal is created by [ value0, value1, ...]. An array element can have any value:, string, constant, object, function, or array. The elements of an array are indexed by integer numbers starting with zero.

[edit] Example

   var arr = [0, function f(){}, {a: "AA", b: "B"}, -1.e-5];
   for (var i = 0; i< arr.length; i++) {console.log(arr[i])}

This yields:

  0 
  (function f() {}) 
  ({a:"AA", b:"B"}) 
  -0.00001 

[edit] Prototype inheritance

JavaScript's prototype inheritance mechanism will be explained by means of a small example.

Every JavaScript function has a property prototype, which is an object with properties that may be inherited by other objects. Certain functions are meant to serve as constructors of objects and it is convention to give those functions names beginning with a capital. In the simple example below the function named C serves as the constructor of the object obj:

[edit] Example prototyping

   var C = function(name){                        // Constructor C
       this[name]  = "Property";
   }
   var obj = new C("prop");                       // create obj
   console.log(obj.hasOwnProperty("prop"));       // => true
   console.log(obj.prop);                         // => Property
   C.prototype.m = function(x){                   // Method m
       return "Returns " + x;
   }
   console.log(obj.hasOwnProperty("m"));          // => false
   console.log(obj.m("XYZ"));                     // => Returns XYZ

[edit] Explanation

The operator new does two things: it creates the object named obj and it executes C with argument "prop". During execution of any constructor function the keyword this obtains the value of the left-hand side of new. In this example this obtains the value obj and during execution of C the object obj is extended with a property named prop having as value the string "Property".

After the creation of obj, the object C.prototype is extended with the method (function) m. For the sake of the example a simple method is chosen: all m does is returning its parameter x prefixed with the string "Returns ".

The crucial point of this example is that m has become a method of obj, invoked as obj.m("XYZ"). The object obj inherits the method m from C.prototype. This inheritance is dynamic: C.prototype.m was created after obj came into existence, yet obj can invoke the method m. Note that m is not an own property of obj, or in other words, it is inherited from C.prototype. Let us reiterate that the function C is the constructor of obj and that obj.m refers to C.prototype.m, not to C.m.

[edit] JavaScript as functional language

Consider the next snippet of JavaScript code. The variable x is local to function host, but not to function nested. However, x is in the lexical environment of nested, meaning that nested has full read/write access to it. Further, functions are "first class objects" and may be returned as values. The statement var fnc=host() invokes host and assigns its return parameter (the function nested) to fnc. After host has finished execution, its local variable x still exists and is accessible by fnc (which is bound to nested).

The function nested is simple, all it does is returning x and adding one to it (the operation ++ adds one and stores the updated x). The function fnc is called twice as argument of the print function console.log.

   function host(){
      var x  = 10;
      function nested(){
           return x++;
      }
      return nested;
   }
   var fnc = host();     // Invoke host; bind fnc to nested
   console.log(fnc());   // => 10
   console.log(fnc());   // => 11

Parameters of the enclosing function also belong to the lexical environment of the nested function. The following code snippet is completely equivalent with the last one, but now x appears as parameter of host:

   function host(x){
      function nested(){
           return x++;
      }
      return nested;
   }
   var fnc = host(10);
   console.log(fnc());   // => 10
   console.log(fnc());   // => 11

A nested function is "closed over" its lexical environment and therefore a function plus its lexical environment is referred to as a closure.

For didactic reasons the host and the nested function were given names ("host" and "nested", respectively). When they are used once only, there is no need for naming them and the following code fragment, in which the names host and nested are dropped, is again equivalent to the two snippets above:

   var fnc = function(x){
         return function (){
                    return x++;
                }
   }(10);
   console.log(fnc());   // => 10
   console.log(fnc());   // => 11

[edit] Application

Closure is at the basis of the following example of JavaScript code running in a web browser. Web browsers offer many methods,among them setInterval, clearInterval, and setTimeout. The following piece of code counts down from 10 to 0 with intervals of one second (1000 msec) and prints the count down variable:

   function host(x){
       var f = function(){console.log(x--);} //update and print x
       var id = setInterval(f, 1000);       //call f every second
       return function(){clearInterval(id)};
   };
   var clear = host(10);  //call host with x=10; bind clear to function
   setTimeout(clear, 11100);         //cancel infinite loop by calling clear after 11 secs

[edit] Explanation

Invocation of the browser (DOM) method: setInterval(f,msec) copies the function f to an internal execution stack and executes it every msec millisecond. Because x is in the lexical environment of f, the closure f can update and print x. The method setInterval continues forever, but returns a process identification number (id) enabling the cancellation of the process. The closure returned by host and bound to the variable clear has access to id and invokes the DOM method clearInterval which cancels the process identified by id. The closure clear is called by setTimeout after 11100 milliseconds, hence after f has been executed eleven times. Note that, in general, the invocation setTimeout(fnc, msec) has two parameters: the function fnc that is called after msec milliseconds.

[edit] Regular expressions

Regular expressions (regexps) form a powerful tool to parse strings. A regexp literal is an object defined between slashes, as in: /pattern/, where pattern is an (often rather intricate) expression that governs the parsing. As an object, a regexp has methods, the most important being the method exec(string). Here the argument string is the string to be parsed.

In the next example a Universal Resource Locator (URL) is parsed into a (i) protocol (i.e., http, htpps, ftp, etc.), (ii) a host, and (iii) a file name (including the path of the file). First, a rather arbitrary URL is assigned as string to the variable url. Second, a regexp literal (between slashes) is assigned to regexp. Then the method exec is invoked, which returns parts broken out of its argument url to elements of the array parsedURL. Finally, the array elements are assigned to variables with meaningful names that are printed.

   var url    = "http://knowino.org/wiki/JavaScript#Regular Expressions";
   var regexp = /^(\w+)\:\/\/([^\/]+)\/(.*)$/;
   var parsedURL = regexp.exec(url);
   var protocol  = parsedURL[1];   
   var host      = parsedURL[2];   
   var path      = parsedURL[3];   
   console.log(protocol);  // => http
   console.log(host);      // => knowino.org
   console.log(path);      // => wiki/JavaScript#Regular Expressions

The main difficulty in the use of regular expressions is the composition of the parsing patterns. These patterns, which must match corresponding parts of the string being parsed, are often hard to read and debug.

In the present example the first caret (^) appearing in regexp means that matching is to begin at the first character of the string and \w means that the first character must be a word character, i.e., a character in any of the ranges [a-z], [A-Z], [0-9], or the underscore (_). The + following \w means that all (with at least one) word characters are matching until the escaped colon (\:) appears. The backslash indicates that the colon is to be taken literally and not to be seen as a special regexp character. In a URL the protocol field is ended with a colon, hence the string beginning with, and consisting of, word characters gives the protocol. The round brackets in (\w+) indicate that the matched string is to be transferred to the array on the left hand side. Hence parsedURL[1] contains the protocol part of the URL (in the example: http).

After the colon the matching is resumed: two slashes are expected in a URL to follow the colon. Since a slash is a character with special meaning, it also has to be escaped by a backslash: \/\/ matches two consecutive slashes. Within square brackets the caret means "not", that is [^\/] matches any character (including white space) except the slash. In other words, a host name can contain any character except a slash. The + indicates again one or more characters and round brackets ask for transfer of the string matched up to \/ (a slash) to the left hand side. Hence parsedURL[2] contains all characters (that can be anything except a slash) between :// and /. Finally, * indicates zero or more matches and $ indicates end of string. Hence, any number of characters (including zero characters) matches the part of the URL that gives the file name and its path.

[edit] References

  1. D. Flanagan, JavaScript, The Definitive Guide, O'Reilly, 6th edition (2011). Lately, also server-side JavaScript has been developed that has more features than the client-side version; see chapter 12 of Flanagan.
  2. ECMAScript 5.1
  3. Mozilla JavaScript Reference
Personal tools
Variants
Actions
Navigation
Community
Toolbox