2.3 - JavaScript¶
The JavaScript language was developed alongside HTML to enable the manipulation of a web page after it has been downloaded to a client. JavaScript runs silently in the background to process user events and dynamically modify a web page. If JavaScript code has problems or produces errors it is designed to fail silently so that the average user is not aware anything went wrong.
JavaScript and Java have nothing in common. They are totally different languages designed for different purposes.
Some of the major distinctions of JavaScript are:
- JavaScript is an interpreted programming language; it is not compiled, though there are some just-in-time (JIT) JavaScript compilers that do increase its execution speed.
- Variables are dynamically typed. The type of data in a variable can change at any time. One moment a variable might contain a string, the next moment a number.
- JavaScript never “crashes”. If an error occurs, the current thread of execution is terminated, but this has no affect on the operation of the web browser.
- JavaScript is a multi-paradigm language that supports ideas from object-oriented programming, imperative programming, and functional programming.
- Everything in JavaScript is an object. In fact, functions are objects!
Learning Javascript¶
If you have limited or no prior programming experience, you need to study JavaScript in depth. The JavaScript tutorials at Code Academy are a good option. The lessons force you to implement the concepts you are learning before moving to the next topic. The tutorials will take a considerable amount of time, but you will learn JavaScript well. If you would like a tutorial that allows you to work through the material at a faster pace, try The Modern JavaScript Tutorial.
If you are an experienced programmer, you can skip the tutorials linked above and just study the document An Introduction to JavaScript for Sophisticated Programmers.
STOP!
Please don’t proceed with the rest of this lesson until you have learned the basics of JavaScript.
Resources¶
This JavaScript Quick Reference Card is a good resource to have by your side as you develop JavaScript code.
Most browsers have a “development environment” where you can experiment with
JavaScript. In Google Chrome, if you right-click anywhere in a web page
and select “Inspect,” the development environment will open. Select the “Console”
tab and you can see the output of console.log()
commands and
you can execute JavaScript commands from the prompt. Try it now!
The remainder of this lesson discusses critical concepts in JavaScript that you must master if you want to understand the WebGL example programs in this textbook.
Context¶
Everything in JavaScript is an object. Objects are instances of a class. Objects contain data and have functions that can manipulate that data. Functions of an object have a context in which they work. Their context is defined by the data they can access and the current state of that data. The idea that every function in JavaScript is executed from a “context” is central to understanding how JavaScript works. Let’s walk through some examples:
- If a function is called because a user clicked on a button, then the function is executed in the context of the HTML button element.
- If a function is called from code loaded from a JavaScript file, then it is executed in the context of the global address space.
- If a function is called from inside an object, then its context is that object.
There is a keyword in JavaScript that always references the
context from which a function is called. The keyword is called this
. The
keyword this
in Java, C++ and other object-oriented programming languages
means something totally different. Do not get them confused.
This is so important that it need to be repeated. In JavaScript, the keyword
this
references the context from which a function is called.
Classes and Objects in JavaScript¶
All of the WebGL programs in this textbook are implemented using objects. Therefore it is critical that you understand how JavaScript implements object-oriented programming.
A class is defined in the same way a normal function is defined. The function
definition is basically the constructor of the class. If you call the function
in the normal way, it will act like a normal function. If you use the new
command in front of the function call you are creating an object.
Hopefully an example will make this clearer. Here is a simple function definition.
function Example(a,b,c) {
// Do some stuff
}
You can call this function in the normal way and it will perform some processing, like this:
Example(alpha, beta, gamma);
Or, you can create an object from the definition like this:
let my_object = new Example(alpha, beta, gamma);
When you create an object, any data defined inside the function is retained inside the object and the data can be accessed and modified at a later time.
Public and Private Data in a Class¶
By default, variables declared inside a function that defines a class
are private. In the following example, all of the data
and functions are private. (By convention, following our coding standard,
private functions will have a name starting with an underscore, _
.)
1 2 3 4 5 6 7 8 9 10 11 12 13 | function ExampleClass(a,b,c) {
// Private class variables
let s,t,u;
// Private functions
function _innerOne() {
// Can manipulate s, t, and u, (and a, b, c).
}
function _innerTwo() {
// Can manipulate s, t, and u, (and a, b, c).
}
}
|
The above example is an immutable object because it has no public data
or public functions. To make an object’s variables or functions
public you add them to the object as properties. Properties of an object
are accessed using dotted notation, as in object.property
. Since
JavaScript is an interpreted and dynamic language, new properties can be
added to an object at any time. This can cause hard-to-find errors if you misspell
property names. Instead of manipulating an existing property, a misspelled
property name will add an new unwanted property to an object. So watch your spelling!
When an object is created by calling the new
command, the this
keyword is a reference to the new object (just like in Java and C++). Therefore,
you can prefix any variable or function with the this
keyword to
make them public. Below is an example class definition that includes
both public and private data and functions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function ExampleClass(a,b,c) {
// Private class variables
let s,t,u;
// Public class variables (actually properties of the object)
this.m = value1;
this.n = value2;
// Public function
this.doSomething = function () {
// Can manipulate all private and public data.
// Can call all private and public functions.
}
// Private function
function _innerOne() {
// Can manipulate all private and public data.
// Can call all private and public functions.
}
}
|
An instance of this class (an object) can be created like this:
let my_object = new ExampleClass(alpha, beta, gamma);
Now that my_object
exists, the following statements are valid
because they are accessing the public members of the object.
my_object.doSomething();
my_object.m = 5;
However, the following statements are invalid because they are attempting to use the private members of the object.
my_object._innerOne(); // would cause a run-time error
my_object.s = 5; // would cause a run-time error
But wait! The above example has a major flaw. The value of the keyword
this
changes with context. When the object is actually used,
the keyword this
will take on various other values besides a reference
to the object and cause the code to fail. The solution is to not use the keyword
this
for accessing public members. Instead, set a reference to the object
as a separate local variable and always use the local reference. The first statement
of a class definition will typically be let self = this
which creates
self
as a local reference to itself. (There is nothing special about the name self
–
you could use any variable name – but using a different name would add more
confusion than it is worth.)
The example below shows how this works. When
the constructor is executed the keyword this
will be a reference to the new
object because of the new
command context. In line 3 a private variable
called self
stores a reference to the new object. Then the local private
variable self
is used throughout the rest of the class definition.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | function ExampleClass(a,b,c) {
let self = this; // store a local reference to the new object
// Private class variables
let s,t,u;
// Public class variables (actually properties of the object)
self.m = value1;
self.n = value2;
// Public function
self.doSomething = function () {
// Can manipulate all private and public data using self.property.
// Can call all private and public functions using self.property.
}
function _innerOne() {
// Can manipulate all private and public data using self.property.
// Can call all private and public functions using self.property.
}
}
|
You are encouraged to re-read the above description. Often the second reading makes more sense.
Garbage Collection¶
In Javascript, you never delete objects. When an object is no longer referenced by any variables, it is automatically deleted and its memory is reclaimed for other uses. This is referred to as garbage collection. Garbage collection is performed automatically at regular intervals and can’t be controlled by a programmer. For a WebGL program that is trying to produce real-time graphics at 30 frames per second, garbage collection is a horrible idea because it can happen at seemly random times and cause disruptions in the smooth flow of an animation. We would like a way to turn garbage collection off, but that is not allowed. Therefore, we do the next best thing and implement our software so it doesn’t create new objects. If there are no un-referenced objects to reclaim, garbage collection happens very quickly and our animations can maintain a smooth 30 frames per second.
To emphasize again, a WebGL program must be very conscience of when new objects are created and minimize the creation of any new objects that might need garbage collection.
Re-definable Functions¶
When a function is defined in JavaScript it automatically becomes part of the global
scope, which is defined by the window
object. The newly defined function
is an object that can be referenced as a property of the window
object.
Therefore, the following two function definitions are basically equivalent.
1 2 3 4 5 6 7 | function ExampleFunction(a,b,c) {
// do some stuff
}
window.ExampleFunction = function (a,b,c) {
// do some stuff
};
|
However, there are subtle differences between these two definitions.
A function that is explicitly defined as a property
of the window
object can be redefined at a future time. To make it possible
to interactively edit the code in this textbook and then restart a WebGL program,
the functions must be defined as window
properties. For a typical WebGL
program, the first definition would be more common.
Some Examples¶
In the WebGL example code below, there are two examples of JavaScript class definitions. Do not attempt to understand the functionality of the code at this time, but rather examine the structure of the class definitions. Please do the following:
- Hide the canvas to make the JavaScript code easier to study.
- Notice the use of strict mode,
"use strict";
at the top of both files. This makes the code less susceptible to spelling mistakes. It requires that all variables be defined before they are used, which means that the constructor code is sometimes not contiguous. - Find the constructor code: (The code that executes once when objects of the class are created.)
- For
object_examples_scene.js
, the constructor code is in lines 44-64 and 112-142. - For
object_examples_events.js
, the constructor code is in lines 34-45 and 139-146.
- For
- Notice how the variable
self
is used to define and access the public members of an object.- For object_examples_scene.js, see the reference to
self
in lines 45 and 60-64. - For object_examples_events.js, see the reference to
self
in line 35 and the public function declarations.
- For object_examples_scene.js, see the reference to
- When studying the code, read the comments!
Some examples of JavaScript class definitions. Ignore the functionality and exam the structure and syntax of the class definitions.
Animate
Coding Standard¶
Before leaving this discussion of JavaScript, please review the coding standard we will be using.
Always include
"use strict";
to force the declaration of variables.Avoid global variables whenever possible.
Use JSLint to check for errors.
Use two-space indentation.
Use shorthand for conditional statements where appropriate:
let results = (test === 5) ? alert(1) : alert(2);
The closing brace should be on the same indent as the original statement:
function func() { return { "name": "Batman" }; }
Naming conventions
Constructors start with a capital letter.
Methods/functions start with a small letter.
Methods/functions should use camel case.
thisIsAnExample
Variables should always use an underscore between words.
this_is_an_example
When appropriate, include the variable type in the name.
value_list
Element ID’s and class names should always use an underscore between words.
Private methods should use a leading underscore to separate them from public methods.
Abbreviations should not be used in names.
Plurals should not be used when assigning names.
Comments should be used within reason.
Use YUIDoc to document functions.
1 2 3 4 5 6 7 8 9 10
/** * Reverse a string * * @param {String} input_string String to reverse * @return {String} The reversed string */ function reverseString(input_string) { // ... return output_string; };
Glossary¶
- JavaScript
- JavaScript is a high-level, dynamic, untyped, and interpreted programming language that is used to manipulate the HTML and CSS code of a web page after the code has been downloaded to a client.
- class
- A construct that defines related data and functions.
- object
- An instance of a class. For example, a class might hold data and functions related to an automobile. Multiple instances of the class can be created to store specific data about individual automobiles.
- object property
- A specific piece of data stored in an object.
- JavaScript
this
keyword - A builtin variable in JavaScript that always references the context in which a function is executing.
- garbage collection
- A process run by your browser that reclaims the memory used by objects that are no longer being used.
Self-Assessments¶
-
Q-36: In JavaScript, how do you define a class and then create instances of the class?
- Define a function; use the "new" command when calling the function.
- Correct.
- Use the keyword "class"; use the "new" command with the "class" name.
- Incorrect, this is the way Java and C++ create and use classes, but not in JavaScript.
- Use the keyword "object"; objects are automatically created as needed.
- Incorrect, there is no keyword "object" in JavaScript.
- Define a function; call the function.
- Incorrect, you do define a function, but you must use the "new" keyword when you call it to create an object.
-
Q-37: In JavaScript, the keyword
- The context in which a function is executed.
- Correct.
- When creating a new object using the "new" command, a reference to the new object.
- Correct. This is the same as "The context in which a function is executed" because the context is the creation of a new object.
- Inside an object's method, the instance of the object that is being executed.
- Incorrect, this is the meaning in Java and C++, but not JavaScript.
- Always refers to the global scope, i.e., the "window" object.
- Incorrect, the meaning of "this" changes based on the context of a function call.
this
refers to what? (Select all that apply.)
-
Q-38: In JavaScript, how do you create “public” members of a class?
- A function is an object and you make the "public" members be properties of the object.
- Correct.
- You use the keyword "public" when you declare them.
- Incorrect, this is how Java and C++ do it, but not JavaScript.
- You declare them using the "let" keyword.
- Incorrect, declaring a variable using "let" makes it a private member.
- All members of a class are automatically "public" unless you specify otherwise.
- Incorrect, the default for variables and functions in a class is to be "private."
-
Q-39: Why should a WebGL program avoid repeatedly creating new objects?
- The memory used by new objects must be reclaimed by the garbage collection process, which can cause real-time animations to loss their frame rate.
- Correct.
- It is just bad programming to create new objects.
- Incorrect, JavaScript is object-oriented and you have to create new objects. You just want to minimize the number of objects that need to be garbage collected.
- Continually creating new objects will cause you to run out of memory.
- Incorrect, because typically the garbage collection process with recover memory for objects that are no longer being used.
- You don't need objects for WebGL programming.
- Incorrect, because even the WebGL context is an object.
-
Q-40: Which of the following function definitions allow the function
to be re-defined after a web page has been loaded?
- window.MyFunction = function(a,b) { ... };
- Correct.
- function MyFunction(a,b) { ... }
- Incorrect.
- let MyFunction = function(a,b) { ... };
- Incorrect.
-
Q-41: In the example WebGL program, the class
- 2
- Correct. The functions are "render()" and "delete()".
- 0
- Incorrect. (Look for properties that are added to "self" and that are set to function definitions.)
- 1
- Incorrect. (Look for properties that are added to "self" and that are set to function definitions.)
- 5
- Incorrect. (Look for properties that are added to "self" and that are set to function definitions.)
ObjectExampleScene
defines how many public methods (i.e., functions)?
-
Q-42: Based on the coding standard we will be using in this textbook, what is
- It is a function because it uses CamelCase.
- Correct.
- It is a function that defines a "class" to create objects because it starts with a capital letter.
- Correct.
- It is a global variable.
- Incorrect.
- It is a local variable.
- Incorrect.
ExampleId
? (Select all that apply.)