In this section we describe "core" JavaScript, that is, as a
programming language apart from its intended use in web pages.
We begin by listing the syntactic similarities between JavaScript and
Java, then we turn to the features of JavaScript that distinguish it.
In this section we describe "core" JavaScript, that is, as a
programming language apart from its intended use in web pages.
- Rules for embedding comments are the same
- Java literals are legitimate JavaScript literals.
In addition, JavaScript has literal syntax for regular expressions,
functions, and objects. (As of Java 8, Java has literal sytax for
functions through lambda expressions.)
- Java identifiers are legitimate JavaScript identifiers.
- In addition, JavaScript allows the use of the dollar sign ('$') in
identifiers.
- JavaScript uses the same operators
(+, >, ==, &&, =, etc) and
precedence rules as Java.
- In addition, Javascript uses === which only returns true if its operands are the
same type and value.
- Java requires a semicolon to terminate a simple (non-block)
statement.
- JavaScript allows the semicolon but does not require it if
statements are on separate lines.
- JavaScript uses the same control structures
(if, for, while, etc) as Java.
- In addition, Javascript allows for (var ... in ...)
(examples later).
Variables can be declared using the
var keyword, but they are
not restricted to any one type:
var x = 13;
...
x = "some string";
Since variables do not have types, type errors are not indicated until
run-time:
var y = 13/"some string";
NaN // value returned by JavaScript interpreter
Javascript allows both named and anonymous functions.
Defining a named function consists of the
function keyword, followed by
- The name of the function
- A list of arguments to the function, enclosed in parentheses and
separated by commas
- The JavaScript statements that define the function, enclosed in
curly braces, { }
Here is a function for computing factorial, and an expression whose
value is factorial of 5:
Anonymous functions are defined similarly but without giving them a
name, similar to
lambda expressions.
Anonymous functions can be used anywhere named functions are expected:
when invoking functions, taking functions as arguments, returning
functions as values, etc.
Below is another expression whose value is factorial of 5. Note:
- The function for computing factorial is iterative rather than
recursive
- The function is not given a name
- The function is called on the argument 5 just as
in fact(5)
A function can be the value of a variable:
Now the variable refers to a function and can be used like one:
foo(5) // value is 120
Objects are the main data type in JavaScript.
There are classes in the ECMA 6 standard, but they are
"syntactic sugar" for the object prototype approach to
inheritance (see constructor functions below).
Objects can have properties and functions (also called
methods)
that can be added dynamically at any time.
Objects can be created in several ways.
The simplest way to create an object is with the
Object
constructor:
var obj = new Object();
Once created, an object can have properties added to it simply by
assigning values:
obj.property = value;
Recall that in Java, this would be done using:
obj.setProperty(value);
Here is an example where an object representing a state of the
Farmer-Wolf-Goat-Cabbage (FWGC) problem is constructed, and four properties
are added:
Here is the rendering:
An
object literal has the form:
{ prop1 : val1, prop2 : val2, ... }
Below is an equivalent way of creating the previous FWGC object, with
the page rendering in the same way:
In the browser:
When creating many similar objects, as in the FWGC problem, it is
useful to create a
constructor function that can be called
repeatedly.
Note that by convention constructor functions capitalize their first
letter.
The need for the
this keyword is explained on the
next slide.
In the browser:
A constructor function
F is intended for use with the
new
operator.
When "
new F(...)" is encountered, three things happen:
- A new object is created (as with "new Object()")
- The function F is invoked, with the newly constructed
object passed in as the value of the this keyword. The body
of F can now give the object state using this.
- The new object is returned as the value of new F(...)
Thus
this in JavaScript constructor functions acts like the
implicit parameter
this in non-static Java methods.
An object
method is a property whose value is a function.
Methods are defined the way normal functions are defined, except that
they have to be assigned as the property of an object.
In the example below, a
toString method is added to the
constructor function for a FWGC state object.
The page rendering is shown on the right. Note that the string
rendering ignores the embedded newline characters ('\n'). We will fix
this in the next section.
An HTML element that displays multi-line strings, that is, those that interpret
newline characters ('
\n'), is "
textarea", which our test file
needs to create.
We can create the
textarea element in two ways:
- Statically, by including it directly in the HTML document,
or
- Dynamically, in JavaScript code using the DOM.
Either way we create the element, we will have to use JavaScript to put
the text returned by the
toString method into it.
We can put a
textarea element into the test file
by introducing the open and close tags directly in the body of
the
div:
This now gives the
div a "child" element, that is,
the
textarea, but the
textarea itself at this point has
no text to display.
The default size of the area will not accommodate the
toString
value, so we can use the
rows and
cols attributes to size
the area:
In the JavaScript code, after retrieving the display
div we can:
- Get the textarea it contains by using the firstChild
property built into the DOM, then
- Give the textarea text to display using its value
property.
The HTML file below produces the display at the right.
To create the
textarea element dynamically in JavaScript:
- Leave the display div empty in the HTML file as
before
- Use the document method createElement to create a
text area
- Use the textarea element's rows property to set
the number of rows to display (this is analogous to
the textarea tag's rows attribute)
- Use the textarea element's cols property to set
the number of columns to display (this is analogous to
the textarea tag's cols attribute)
- Add the textarea element to the body of the div
using the appendChild method built into the DOM
The HTML file below produces the display at the right.
HTML pages with a significant amount of JavaScript code often have their
code separated out from the HTML pages that use it.
JavaScript files usually have a
.js suffix.
When an HTML page needs to use JavaScript code that is contained in a
separate file, say
file.js, it uses the
script element with
a
src attribute in the following way:
<script src="file.js"></script>
In order to make calls to code contained in
file.js, the HTML
page can include another
script element with a body:
<script>
...code that uses code in file.js...
</script>
The JavaScript factorial code is shown below in
factorial.js — note the absence of the
script
element.
The HTML test file
factorial.html loads
factorial.js
using the
src attribute.
The rendering of
factorial.html is show to the right.
factorial.js
factorial.html
In this example we separate the JavaScript code into three files whose
source can be viewed through the menu at the left:
- FarmerState.js: A FarmerState constructor function
with methods toString, safe, and equals
- test-utils.js: Contains generally useful testing
functions, including an assert function that behaves like
its Java counterpart
- FarmerStateTest.js: Constructs and
displays FarmerState objects and makes assertions testing
their methods
The top-level HTML file that loads this code and displays results is
listed below.
FarmerStateTest.html
Note the use of a helper function
alone. It is not a method
of
FarmerState and so is defined outside
FarmerState's
scope.
This file defines functions that support testing the
FarmerState
constructor. It makes use of these further features of JavaScript and
the DOM:
- The br DOM element corresponding to the HTML tag that
produces a line break (new line) in the page output
- The span DOM element that, like div, is a container for
document content, but that content is contained within a single
line of the display
- The style property of DOM elements (in this
case, span), that is used to provide CSS styling (in this
case, color). CSS (Cascading Style Sheets) will be discussed
later.
- The built-in JavaScript function eval that takes an
expression as a string and evaluates it. In this case it is used
to implement an assert function like that employed by
JUnit.
This file creates a number of
FarmerState objects and tests
their display, safety, and equality.
Note that it makes a number of calls to
assert, with expressions
that should evaluate to
true.
The output is shown to the right.
Note one false assertion that
displays in red.
Browser consoles are also helpful in debugging JavaScript.
Suppose we render the HTML file below, which contains an error
— can you spot it?
The display, shown on the right, is empty, signifying an error.
When an error occurs, open the browser's console
using
Ctl-Shift-I to see the error message.
factorial-error.html
When the browser console displays the first time, it may have a lot of
logging information in it. Clear the console by clicking the trashcan icon:
If you run the erroneous HTML file shown above, nothing will be
displayed in the associated browser tab.
When this happens, look in the
browser console for an error message. In this case, the error message
is displayed and the file and line number are given:
The Chrome/Chromium console reports the error as shown below. It also
provides the file name and line number.
When the console appears, it will contain the error message, file name,
and line number: