Some features of javascript

Version 5

© Copyright John G Harris, 2002-2017

You have permission to copy this document for teaching and learning purposes.

0 Contents

0Contents

1Introduction

2Context

2.1Names

2.2Comparison with other languages

2.3Use

2.4Compatibility

3Variables and values

3.1Numbers

3.2Declaration

3.3Implicit type conversion

4Objects

4.1The prototype chain

4.2Construction

4.3"Class"

4.4Arrays

A1Examples

A1.1An example of inheritance

A1.2An example of form validation

1 Introduction

This note describes the significant features of the javascript programming language. It concentrates on the features likely to cause surprise, if not shock and horror. It is written as a series of somewhat disconnected topics.

2 Context

2.1 Names

JavaScript
A trademark owned by Sun and then Oracle, used with permission by the Mozilla organisation. The language was invented for the Nescape Navigator browser and originally called LiveScript. The name was changed to make the language more visible.
JScript
A trademark owned by Microsoft.
ECMAScript
The name used in the specification of the core language. It was used to avoid a clash of trademark names.
(ECMA is the European Computer Manufacturer's Association. Its committees have produced many industry standards).
javascript
Generic name used here and in the names of MIME types.

2.2 Comparison with other languages

Javascript uses the same general syntax as C++ and Java, e.g.

a = b + 2;

if (...) ...

while (...) ...

for ( ...; ...; ...) ...

Declaring variables and defining functions is somewhat different, e.g.

var x; // Declare a variable

function f() { ... } // Define a function

Semicolons can be omitted in certain circumstances.

The way objects work is very, very, VERY different.

2.3 Use

The most prominent use of javascript is to automate web pages in the client PC, but this is not its only use :-

In web pages, executed by the browser
Manipulate the web page while it is being displayed.
Check values in forms before they are sent to the web server for processing.
Implement Windows-style popup menus.
etc.
In Microsoft Windows HTML Help (.chm) files
Much the same as in web pages.
In web servers
General purpose programming language for creating dynamic web pages.
In Windows
The "Microsoft Scripting Host" understands javascript (.js) files, also .bat files etc.

2.4 Compatibility

The core language is specified in the ECMAScript standard, ECMA 262. Extremely old browsers might differ in a few details. Note, though, that the standard has additional language features added from time to time. Such features will not be implemented by older browsers, and in some cases not initially by up-to-date browsers.

Javascript code embedded in an HTML document can alter the HTML content as the page is being loaded, and when loaded can access images, data in forms, etc as well as altering the page content further. The various browsers are converging towards a common W3C standard for these facilities. As with the core language, older browsers may be incompatible and newly specified facilities can take time to be implemented.

ECMA 262 is available at the ECMA web site. Programming manuals for non-core browser features are available at the Mozilla and Microsoft web sites. The target browser standard for accessing the HTML document structure, "the DOM", is available at the W3C web site. (URLs are not given as they change too often).

3 Variables and values

Any javascript variable can hold any value of any type. Thus

x = 5; x = "UMIST"; x = true;

is perfectly legal. The javascript types are :-

Undefined
one value : undefined
Number
primitive numbers (see below)
String
primitive strings
Boolean
two values : true, false
Object
an object (of any kind)
Null
not anything else
one value : null

If y holds an object then

x = y;

makes x and y hold the same object.

Note that in Java the values held by the variables x and y would be references, both being references to the same object. In ECMAScript the values are the object itself. Either way, the names "x" and "y" now refer to the same object.

3.1 Numbers

All javascript numbers are 64 bit IEEE 754-2008 floating point numbers. However, the integral values 0.0, 1.0, 2.0, -1.0, etc can be treated as integers provided they are no bigger than 253.

The operators +, -, *, and % preserve integral values. The division operator, /, can produce small but annoying rounding errors and these errors can vary with browser version.

3.2 Declaration

There are three ways to introduce a variable :-

First, inside a function definition

var v;

makes v a local variable.

Second, outside any function definition

var v;

makes v a global variable.

Third, if v is not declared as a global variable anywhere in the program and is not a current local variable then

v = ...;

makes v a global variable. This is obviously a good source of programming errors!

Variables can be initialised at declaration, as in

var v = 5;

There are no block variables. A variable is either global or local to a whole function.

However, in 2015 two other kinds of variable were introduced that do have block scope. They are declared using the keywords const and let instead of var.

3.3 Implicit type conversion

There is a distressing tendency to convert any value into a string whenever a string is desired. Thus

"M" + 2 + 2

is "M22", whereas

"M" + (2 + 2)

is "M4".

4 Objects

Each javascript object is an evolving associative array, alias evolving family, alias evolving FoC Dictionary [1]. In fact, the internal state and behaviour of an object is modelled precisely by FoC's Dictionary class and its operations.

In outline, each object is a collection of properties. Each property has a name and a value. The value can be any member of any of the javascript types. The name is either a string conforming to the rules for javascript identifiers, or a private name that cannot be used directly (see later), or a string numeral used only by the special Array objects (also see later).

The structure of an object

Properties can be accessed using array notation. Suppose a is a variable whose value is an object. Then a["b"] denotes the value of the property named "b" in the object a. Dot notation can also be used : a.b is defined to mean the same as a["b"]. This can be taken further. If x's value is the string "b" then a[x] also means the same as a["b"], alias a.b.

Assignment to a property causes it to be created if it does not already exist. The delete operator can be used to remove a property, though this is seldom necessary in practice. Note that objects themselves are destroyed by the automatic background garbage collector, not by the program.

The javascript interpreter translates function definitions into Function objects. These objects can be assigned to properties just as any other kind of object. Thus, if we define

function fun() { ... }

we can assign the resulting Function object to a property as in

a.f = fun;

From now on

a.f()

denotes a call of the function. Obviously, we will often want the function to access the properties of a. The execution environment maintains a global pseudo-variable, this. When a.f is called the value of this becomes the object a. If the function contains the statement

this.b = 42;

then the call

a.f();

changes the value of a.b to 42. Properties whose values are Function objects are often called methods to emphasise their function nature.

There is a minor complication. Each property has a hidden set of "attributes", such as read-only. In user-created properties the set is empty by default. From version 5 of the core language user programs can set the attributes on and off.

[1] Scheurer, T [1994]. Foundations of Computing : System development with set theory and logic. Addison-Wesley.

4.1 The prototype chain

Suppose we have several objects holding different data values but holding the same set of Function objects. If there are a lot of objects and a lot of common functions then the result could be an inefficient use of storage and execution time. A neater design would be to use a separate object to hold all the Function objects. Javascript provides a facility to do this in an efficient way. The picture below shows how it is done.

An object's prototype chain

Every javascript object is constructed (see later) with a particular property that holds another object, or is null. The property's name is private; the word proto has been used here for convenience. The object held by the proto property, if any, is called a prototype.

The chain of prototype objects is used during read access to a property. To find the value of a.b the javascript engine searches up the prototype chain from the object a. It uses the value of the first property named "b" that it finds; the result is undefined if none is found. This mechanism applies to methods as well, of course. In the picture, if the object at the bottom of the picture is held by the variable person then person.age() denotes a call to the Function object held by the prototype object at the top of the picture.

In contrast, during write access to a.b the javascript engine does no search. The object a is given a new property named "b" if it did not have one already. This new property hides any "b" properties in the prototype chain in subsequent accesses.

Note that prototype objects are just ordinary objects used in a particular way.

4.2 Construction

An object is created when an expression comprising the keyword new followed by a function call is executed. First, a raw object is created, then some private properties, such as the proto property, are inserted, then the function is called with the value of this being the new object. Any user-defined function and many built-in functions can be used here. Obviously, the function will usually be one that adds some properties to the new object. On the other hand, the expression

new Object()

creates an object with no user-defined properties. It is sometimes more convenient to add properties later on.

Every Function object has a public property named "prototype". Its value is copied** to the proto property of every object constructed by the function. For example, to use the function Thing to create objects whose prototypes will be the object currently held by protoThing do

function Thing() { ... }

Thing.prototype = protoThing;

Now

new Thing()

will create objects with the desired prototype object.

** Note
This changed in version 3 of the core language, as follows. If Thing.prototype is null or any other non-object type, then an internal default prototype object is used instead. This default object's proto value is null. Because of these rules the default object is at the end of every prototype chain. Its methods, isPrototypeOf etc., are therefore available in every object.
 
More recent versions of the core language have introduced ways, not using new, to create objects with a proto value of null if this is wanted.

4.3 "Class"

The word "class" must be used with some care in a javascript context.

The first reason is that class was a reserved word before version 6 of the core language. It then became a keyword that allowed the use of C++/Java-style class definitions. We must make it clear whether "class" is referring to this (optional) facility or is being used with a more general meaning.

The second reason is that objects can be modified dramatically after creation. Suppose we have a function Thing and we use new Thing() to create several new objects. It is natural to call them Thing objects, and to say that they belong to the Thing class. However, we could add and remove properties in some of these objects. We could even change Thing.prototype and create some more Thing objects. We could now have two Thing objects that have no data properties and no method properties in common! "Thing class" has a less constrained meaning than it does in other programming languages.

4.4 Arrays

Javascript includes facilities for creating and using arrays. For instance,

var a = new Array();

a[0] = 5;

a[1] = 7;

var x = a[0] + a[1];

does what you would expect. What you might not expect is that

var a1 = new Array();

a1[2000000000] = "Wow!";

does not upset your computer.

The elements of an Array object are implemented as properties. An element occupies no storage space until it is written to. That is, javascript arrays are sparse arrays. What is special about Array objects is that they are allowed to have properties whose names are numeric strings such as "0" and "5". Thanks to implicit type conversion, the sequence

x = 1;

a[x] = 13;

means the same as

a["1"] = 13;

which causes the property named "1" to be given the value 13.

A1 Examples

A1.1 An example of inheritance

Here is an example of a systematic way to implement inheritance that will work for any number of layers.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">

<HTML>
<HEAD>
  <TITLE>Javascript example : Inheritance</TITLE>

  <STYLE type="text/css">
    BODY      { font-family: Arial, Helvetica, sans-serif;
                color: black; background: rgb(255,255,210) }
    A:link    { color: rgb(0,0,255); }
    A:visited { color: rgb(255,0,0); }
    H1,H2,H3,H4,H5,H6
              { text-align: center; color: rgb(153,102,0); }
    .copyr    { font-family: Arial, Helvetica, sans-serif;
                text-align: center; color: rgb(153,102,0); }

    .indent   { margin-left: 1em; }
  </STYLE>
  
<SCRIPT type="text/javascript">

    // Surname type (base class)

  function protoSurname()
      // Construct a prototype object for the Surname type
    {
      this.SurString = function()
        { return this.surname; }
      this.toString = this.SurString;
    }
  protoSurname.prototype = null;

  function Surname(aSurname)
      // Construct an object of the Surname type
      //   Object property is surname
      //   Public method is toString
    {
      this.surname = aSurname;
    }
  Surname.prototype = new protoSurname();
  


    // Fullname type (sub class)

  function protoFullname()
      // Construct a prototype object for the Fullname type
    {
      this.FullString = function()
        { return this.forename + " " + this.SurString(); }
      this.toString = this.FullString;
    }
  protoFullname.prototype = Surname.prototype;

  function Fullname(aForename, aSurname)
      // Construct an object of the Fullname type
      //   Object properties are forename, surname
      //   Public method is toString
    {
      this.base = Surname;  // Ensure 'this' is passed on
      this.base(aSurname);
      delete this.base;
      this.forename = aForename;
    }
  Fullname.prototype = new protoFullname();



    // Qualname type (sub sub class)

  function protoQualname()
      // Construct a prototype object for the Qualname type
    {
      this.QualString = function()
        { return this.title + " " + this.FullString(); }
      this.toString = this.QualString;
    }
  protoQualname.prototype = Fullname.prototype;

  function Qualname(aTitle, aForename, aSurname)
      // Construct an object of the Qualname type
      //   Object properties are title, forename, surname
      //   Public method is toString
    {
      this.base = Fullname;  // Ensure 'this' is passed on
      this.base(aForename, aSurname);
      delete this.base;
      this.title = aTitle;
    }
  Qualname.prototype = new protoQualname();

</SCRIPT>

</HEAD>
<BODY>
  <H1> Javascript example : Inheritance </H1>

  <P>
    Create three objects and then use them to render their values in
    this page :-

  <DIV class="indent">
  <SCRIPT type="text/javascript">

      // Examples

    var a = new Surname("Harris");
    document.writeln("<P>", a);

    var b = new Fullname("William", "Gates");
    document.writeln("<P>", b);

    var c = new Qualname("Dr", "John", "Stockton");
    document.writeln("<P>", c);

  </SCRIPT>
  </DIV>

<P class="copyr"> &#169; Copyright John G Harris, 2002-2003

</BODY>
</HTML>

  

A1.2 An example of form validation

Here is an example of the use of javascript to vet values in a form before they are submitted to a web server.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">

<HTML>
<HEAD>
  <META http-equiv="Content-Script-Type" content="text/javascript">
  
  <TITLE> Javascript example : Validation </TITLE>

  <STYLE type="text/css">
    BODY      { font-family: Arial, Helvetica, sans-serif;
                color: black; background: rgb(255,255,210) }
    A:link    { color: rgb(0,0,255); }
    A:visited { color: rgb(255,0,0); }
    H1,H2,H3,H4,H5,H6
              { text-align: center; color: rgb(153,102,0); }
    .copyr    { font-family: Arial, Helvetica, sans-serif;
                text-align: center; color: rgb(153,102,0); }

    FORM      { background: rgb(210,255,255);
                margin-left: 30%; margin-right: 30%; } 
    .TextBox  { margin-top: 3em; margin-bottom: 3em;
                margin-left: 20%; margin-right: 20%; }
  </STYLE>


  <SCRIPT type="text/javascript">

    function Vet(form)
      // Vet the form and return true iff values are ok
    {
      return ( VetText(form, "Name") &&
               VetInt(form, "Width", 3, 9) );
    }


    function VetText(form, field)
      // Vet a text field
    {
      if (form[field].value == "")
        {                               
          alert("Data error :\n<" + field + "> must not be empty");
          return false;
        }
      return true;
    }


    function VetInt(form, field, min, max)
      // Vet an integer field
    {
      if (!VetText(form, field))
        return false;

      var n = parseInt(form[field].value, 10);

      if (isNaN(n))
        {   
          alert("Data error :\n<" + field + "> must be a number");
          return false;
        }

      form[field].value = n;

      if ( (n < min) || (n > max) )
        {
          alert("Data error :\n<" + field +
                "> must be in the range " + min + "..." + max);
          return false;
        }
      return true;
    }

  </SCRIPT>
</HEAD>


<BODY>
<H1>
  <A name="top"> Javascript example : Validation </A>
</H1>

<DIV class="TextBox">
<P>
  The data in the form is vetted when the Submit button is pressed.
  If Name and Width have improper values then an error message
  is displayed and the data is not submitted.
</P>
<P>
  Notice that the URL displayed by the browser changes only when
  Submit is accepted. Notice also that the width number is cleaned
  up before it is sent. E.g&nbsp;4B is sent as 4
</P>
</DIV>

<FORM action="#top" method="GET" onsubmit="return Vet(this);">
  <H2>Simple form</H2>
  <P>
    <INPUT type="TEXT" name="Name" size="20"> Name <BR>
    <INPUT type="TEXT" name="Width" size="20"> Width
  </P>
  <P>
    <INPUT type="SUBMIT" value="Submit">
    <INPUT type="RESET" value="Clear">
  </P>
</FORM>

<HR>
<P class="copyr"> &#169; Copyright John G Harris, 2002-2003

</BODY>
</HTML>