-
1. What is JavaScript
- A short history
-
JavaScript Implementations
-
ECMAScript
-
Not tied to host environment
- Web browser is just one host environment, tied to JavaScript but not ECMAScript
- Other host enviroments includes NodeJS, Adobe Flash, etc
- A host environment provides the base
- implementation of ECMAScript
- implementation of extensions designed to interface with the enviroment itself, e.g. DOM
-
It describes the following parts of the language
- Syntax
- Types
- Statements
- Keywords
- Reserved words
- Operators
- Objects
- JavaScript implements ECMAScript, but so does Adobe ActionScript
-
ECAMScript Editions
- Most recent edition: 5th for this book, 11st for now
- 1st edition
- basically JavaScript 1.1 but with ...
- browser-specific code removed
- unicode standard supported
- objects being platform-independent
- 2nd edition
- get into strict agreement with ISO/IEC-16262
- 3rd edition
- string handling
- definition of errors
- numeric outputs
- support for regular expressions
- new control statements, e.g. for, while...
- try-catch exception handling
- internationalization
- 4th edition
- big changes, defined an almost completely new language, was abondoned because of too big a jump
- 5th edition
- smaller change that could be implemented on top of existing JavaScript, won over the 4th edition
- published on December 3, 2009
- introduced addtional functionality
- native JSON object for parsing and serializing JSON data
- methods for inheritance and advanced property definition
- strict mode
-
ECMAScript Conformance
- Support all "type, values, objects, properties, functions, and program syntax and semantics" as they are described in ECMA-262
- Support the unicode character standard
- Add "additional types, values, objects, properties, and functions" that are not specified in ECMA-262
- Support "program and regular expression syntax" that is not defined in ECMA-262
-
ECMAScript support in web browsers
- Netscape3 + JavaScript 1.1
- IE3 + JScript 1.0
- Netscape4 + JavaScript 1.2
- IE4 + JScript 3.0
- Netscape 4.06 + JavaScript 1.3
- By 2008, the five major web browsers all complied with the 3rd edition
- IE8 was the first to start implementing the 5th edition and delivered the complete support in IE9
- Firefox 4 soon complied 5th edition
- compliant with 1st edition
- Not compliant with ECMA-262
- compliant with 5th edition
- compliant with 3rd edition
-
Document Object Model (DOM)
-
Definition
- The Document Object Model (DOM) is an application programming interface (API) for XML that was extended for use in HTML.
- XML: Carry or store data
HTML: Display data
-
Hierarchy
- <html>
<head>
<title>Sample Page</title>
</head>
<body>
<p> Hello World!</p>
</body>
</html>
- Nodes can be removed, added, replaced, and modified easily by using DOM API
-
Why DOM is necessary
- Netscape and Microsoft went separate ways in developing DHTML, if someone didn't rein in Netscape and Microsoft, the web would develop into two distinct factions
- It was then that the Wrold Wide Web Consortium (W3C) began working on the DOM
-
DOM Level
- DOM Level 1
- became a W3C recommendation in 1998.10
- consisted of two modules
- DOM core
- provided a way to map the structure of an XML-based document
- allowed for easy access to and manipulation of any part of a document
- DOM HTML
- extended the DOM core
- added HTML-specific objects and methods
- DOM Level2
- consisted of
- DOM views
- Describes interfaces to keep track of the various views of a document
https://www.w3.org/TR/2000/REC-DOM-Level-2-Views-20001113/views.html
- DOM events
- Describes interfaces for events and event handling
- DOM style
- Describes interfaces to deal with CSS-based styling of elements
- DOM traversal and range
- Describes interfaces to traverse and manipulate a document tree
- DOM Level3
- consisted of
- methods to load and save documents in a uniform way (DOM Load and Save)
- methods to validate a document (DOM Validation)
- support all of XML 1.0, including XML infoset, XPath, and XML Base
- DOM4
- Presently the W3C no longer maintains the DOM as a set of levels, but rather as the DOM Living Standard, snapshots of which termed DOM4
- added Mutation Observers to replace Mutation Events
- Other DOMs
- several other languages have had their own DOM standards
- Scalable Vector Graphics (SVG) 1.0
- Mathematical Markup Language
(MathML) 1.0
- Synchronized Multimedia Integration Language (SMIL)
- standard recommendations from W3C
- some other languages have developed their own DOM implementation
- Mozilla's XML User Interface Language (XUL)
-
DOM support in Web browsers
- IE made its first attempt with version 5
- IE implemented most of DOM Level 1 with version 5.5
- IE9+ supported all DOM levels
- Netscape started supporting DOM with Netscape 6 (Mozilla 0.6.0)
- After Netscape 7, Mozilla switched its efforts to the Firefox browser
- Firefox 3+ supports all of Level 1, nearly all of Level 2, and some parts of Level 3
- Now, all of the major browsers have supported all DOM standards
-
Browser Object Model (BOM)
- IE3 and Netscape3 featured a browser object model that allowed access and manipuation of the browser window
-
It was the only part of a JavaScript implementation that had no related standard
- There are some de facto standards, such as window and navigator object, but each browser defines its own properties and methods
- Thanks to HTML5, which codified much of the BOM as part of a formal specification
-
BOM deals with
- browser window
- browser frames
- In the context of a web browser, a frame is a part of a web page or browser window which displays content independent of its container, with the ability to load content independently.
- any browser-specific extension to Javascript
- pop up new browser windows
- move, resize, and close browser windows
- the navigator object
- provides detailed information about the browser
- the location object
- gives detailed information about the page page loaded in the browser
- the screen object
- gives detailed information about the user's screen resolution
- the performance object
- gives detailed info about the browser's memory consumption, navigational behaviour, and timing statistics
- support for cookies
- costom objects
- XMLHttpRequest
- Internet Explorer's ActiveXObject
-
JavaScript Versions
-
Mozilla, as a descendant from the original Netscape, is the only browser vendor that has continued the original JavaScript version numbering sequence
-
Most browsers talk about JavaScript support in relation to their level of ECMAScript compliance and DOM support
- e.g. https://www.w3schools.com/js/js_versions.asp
-
2. JavaScript in HTML
-
The <Script> element
-
Intro
- Primary method of inserting JavaScript into an HTML page
- Created by Natscape and first implemented in Netscape navigator 2
-
7 attributes
- async
- optional
- indicates that the script should begin downloading immediately but should not prevent other actions on the page
- valid only for external script files
- charset
- optional
- the character set of the code specified using the src attribute
- <script charset="UTF-8" src="demo_script_charset.js">
http://a4esl.org/c/charset.html
- rarely used because most browsers don't honor its value
- crossorigin
- optional
- configures the CORS settings for the associated request, by default CORS is not used at all
- crossorigin="anonymous" will not set the credentials flag
- crossorgin="use-credentials" will set the credential flag, meaning the outgoing request will include credentials
- defer
- optional
- indicates that the execution of the script can safely be deferred until after the document's content has been completely parsed and displayed
- valid only for external scripts
- IE 7 and earlier also allow for inline scripts
- integrity
- optional
- allows for verification of Subresource Integrity (SRI) by checking the retrieved resource against a provided cryptographic signature.
- useful for ensuring that a Content Delivery Network is not serving malicious payloads
- language (deprecated)
- src
- optional
- indicates an external file that contains code to be executed
- type
- optional
- replaces language
- indicates the MIME type
- application/x-javascript
-
2 ways to use <script>
- embed directly into the page
- You cannot have "</script>" anywhere in the code
- <script>
function sayScript() {
console.log("</script>");
}
</script>
Above will cause an error
- <script>
function sayScript() {
console.log("<\/script>");
}
</script>
Ok to use with escaping character
- include from an external file
- <script src="example.js"></script>
- .js extension is not required, which open the possibility of dynamically generating JavaScript code using a server-side scripting language, or for in-browser transpilation into Javascript from a JavaScript extension language such as TypeScript or JSX
- Servers often use the file extension to determine the MIME type, so be sure to double-check it is returning the correct MIME type
- should not include inline script otherwise will be ignored
- There is also some time taken to download the file
- Processing of the page is halted while the external file is interpreted
-
Script src supports JavaScript file outside the domain
- <script src="http://www.somewhere.com/afile.js"></script>
- It will send a GET request to get a file
- This initial request is not subject to the browser's cross-origin restriction, but any JavaScript returned and executed will be
- Make sure you are the domain owner or the external domain is owned by a trusted source
-
Order of multiple script elements
- From top to bottom, the above one must be completedly interpreted before the second
- async and defer can change the order
-
Tag Placement
-
Traditionally was placed within the <head> element on a page
- <!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script src="example1.js"></script>
<script src="example2.js"></script>
</head>
<body>
<!-- content here -->
</body>
</html>
- Main purpose was to keep both CSS and JS files in the same area
- However, JS code will be downloaded, parsed, and interpreted before the page begin rendering, thus causing a noticeable delay before page rendering (people will see blank page)
-
Modern webs includes all JS references before </body>
- <!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
</head>
<body>
<!-- content here -->
<script src="example1.js"></script>
<script src="example2.js"></script>
</body>
</html>
- Page is rendered before JS processing, reducing the time on blank page
-
Deferred scripts
- <!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script defer src="example1.js"></script>
<script defer src="example2.js"></script>
</head>
<body>
<!-- content here -->
- Signals the browser to begin downloading immediately but execution should be deferred after the entire page has been parsed
- The HTML5 specification indicates that scripts will be executed in the order in which they appear, and will execute before the DOMContentLoaded event
- In reality, though, deferred scripts don't always execute in order or before the DOMContentLoaded event, so it's best to include just one when possible.
-
Not work for inline script
- except IE 4-7
- Support begin with IE4, Firefox3.5, Safari 5, Chrome 7, other browsers will simply ignore this attribute. So it is still best to put deferred scripts at the bottom of the page
-
Asynchronous scripts
- <!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script async src="example1.js"></script>
<script async src="example2.js"></script>
</head>
<body>
<!-- content here -->
</body>
</html>
- Signals the browser to begin downloading files immediately, but not guarantees the order of execution in which they are specified.
- Make sure there are no dependencies between the files, and files are not modifying DOM as they are loading
-
Guaranteed to execute before the page's load event, and may execute before or after DOMContentLoaded
- not use document.write
-
Dynamic script loading
-
let script = document.createElement('script');
script.src = 'gibberish.js';
script.async = false;
document.head.appendChild(script);
- By default, scripts created in this fashion are async, but since not all browsers support async, we should set async to false to unify behaviour.
- However, this can severely damage performance since resources fetched in this fashion will be hidden from browser preloaders.
- To inform preloaders, you can explicitly declare the link in the document head
- <link rel="subresource" href="gibberish.js">
-
Changes in XHTML
- XHTML is a stricter, more XML-based version of HTML
- In XHTML, the <script> element requires that you specify the type attribute as text/javascript.
-
<script type="text/javascript">
function compare(a, b) {
if (a<b) {
console.log("A is less than B");
} else if (a>b) {
console.log("A is greater than B");
} else {
console.log("A is equal to B");
}
}
</script>
- <b is invalid in XHTML since it is interpreted as the beginning of a tag
- Two solutions
- Replace < with <
---------------------------------
if (a<b) {
console.log("A is less than B");
}
- Wrap in a CDATA
---------------------------------
<script type="text/javascript">
//<![CDATA[
function compare(a, b) {
if (a < b) {
console.log("A is less than B");
} else if (a> b) {
console.log("A is greater than B");
} else {
console.log("A is equal to B");
}
}
//]]>
</script>
- Many browsers (non XHMTL-compliant) don't support CDATA section so CDATA markup must be offset by JS comments
-
Deprecated Syntax
- Unless you are using XHTML or the <script> tags for non-JavaScript, the best practice is to not specify a type since MIME type are not standardized across browser
-
<script><!--
function sayHi(){
console.log("Hi!");
}
//--></script>
- Hide embedded JS code from the browser that didn't support it
- Not needed any more for modern browsers
-
Inline code v.s. External files
-
Best practice is to use external files
- Maintainability
-
Caching
- Browsers cache all JS files according to specific settings. If two pages are using the same file, the files is downloaded only once.
-
Future-proof
- No need to use XHTML comment hacks
-
Document modes
- Introduced by IE5.5
-
modes
-
quirks
- Make IE behave if it were IE 5 with several nonstandard feature
- Triggered by omitting the doctypes
-
standards
- Make IE behave in a more standards-compliant way
- Triggered by using doctypes
- <!-- HTML 4.01 Strict -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<!-- XHTML 1.0 Strict -->
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!-- HTML5 -->
<!DOCTYPE html>
-
almost standards
- has a lot of the features of standards mode but isn't as strict
- Treatment of spacing around images, especially in tables
- Triggered by transitional and frameset doctypes
- <!-- HTML 4.01 Transitional -->
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!-- HTML 4.01 Frameset -->
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<!-- XHTML 1.0 Transitional -->
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- XHTML 1.0 Frameset -->
<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Frameset//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-
The <noscript> element
- Disable JavaScript
-
Content contained in it will be displayed
- When the browser doesn't support scripting
- When the browser's scripting support is turned off
- Can contain any HTML elements except for <script>
- <!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script ""defer="defer" src="example1.js"></script>
<script ""defer="defer" src="example2.js"></script>
</head>
<body>
<noscript>
<p>This page requires a JavaScript-enabled browser.</p>
</noscript>
</body>
</html>
-
3. Language Basics
-
Intro
- Based primarily on ECMAScript 6th edition
-
Syntax
- Everything is case-sensitive
-
Identifiers
- First character must be a letter, _, or $
- All others may be letters, _, $, or numbers
- Letters in an identifier may include extended ASCII or Unicode letter characters such as À and Æ, not recommended
- By convention camel case
-
Comments
- // or /* xxx */
-
Strict mode
- Strict mode is a different parsing and execution model for JavaScript, where some of the erratic behavior of ECMAScript 3 is addressed and errors are thrown for unsafe activities.
-
You can use it at the top of a script or specify in a function
- function doSomething() {
"use strict";
// function body
}
-
Statements
- Terminated by a semicolon ;
(not required but best practice)
- Alway use {} for if
(not required for one line statement but best practice is to always have it)
-
Keywords and reserved words
-
Current reserved
- break do in typeof
case else instanceof var
catch export new void
class extends return while
const finally super with
continue for switch yield
debugger function this default
if throw delete import try
-
Future reserved
- Always reserved: enum
-
Reserved in strict mode
- implements package public
interface protected static
let private
-
Reserved in module code
- await
-
Variables
- loosely typed, meaning that variable can hold any type of data
-
var
- undefined if declare without initialization
-
Using var to define a variable makes it local to the function scope
- function test() {
var message = "hi"; // local variable
}
test();
console.log(message); // error!
-
Define a variable globally by omitting var
- function test() {
message = "hi"; // global variable
}
test();
console.log(message); // "hi"
- Not recommended, hard to maintain, strict mode will throws a ReferenceError
-
var hoisting
- function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined
- =
function foo() {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
-
let (introduced in ECMA 6)
-
similar to var except that let is block scoped, var is function scoped
- if (true) {
var name = 'Matt';
console.log(name); // Matt
}
console.log(name); // Matt
if (true) {
let age = 26;
console.log(age); // 26
}
console.log(age); // ReferenceError: age is not defined
-
does not allow for any redundant declarations within a block scope
- var name;
var name;
let age;
let age; // SyntaxError; identifier 'age' has already been declared
-
does not support hoisting
- // name is hoisted
console.log(name); // undefined
var name = 'Matt';
// age is not hoisted
console.log(age); // ReferenceError: age is not defined (refered as temporal dead zone)
let age = 26;
-
when using let in the global context, it will not attach to the window object as they do with var
- var name = 'Matt';
console.log(window.name); // 'Matt'
let age = 26;
console.log(window.age); // undefined
- Persis for the lifetime of the page
-
conditional declaration
- <script>
var name = 'Nicholas';
let age = 26;
</script>
<script>
// Suppose this script is unsure about what has already been declared in the page.
// It will assume variables have not been declared.
var name = 'Matt';
// No problems here, since this will be handled as a single hoisted declaration.
// There is no need to check if it was previously declared.
let age = 36;
// This will throw an error when 'age' has already been declared.
</script>
- try (age) {
// If age is not declared, this will throw an error
}
catch(error) {
let age;
}
// 'age' is restricted to the catch {} block scope
-
loop
- for (var i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// You might expect this to console.log 0, 1, 2, 3, 4
// It will actually console.log 5, 5, 5, 5, 5
- for (let i = 0; i < 5; ++i) {
setTimeout(() => console.log(i), 0)
}
// console.logs 0, 1, 2, 3, 4
-
const (introduced in ECMA 6)
-
Similar to let exception that it must be initialized with a value, and that value cannot be redefined after declaration
- const age = 26;
age = 36; // TypeError: assignment to a constant
- // const still disallows redundant declaration
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError
- // const is still scoped to blocks
const name = 'Matt';
if (true) {
const name = 'Nicholas';
}
console.log(name); // Matt
- const person = {};
person.name = 'Matt'; // ok
- for (const i = 0; i < 10; ++i) {} // TypeError: assignment to constant variable
- let i = 0;
for (const j = 7; i < 5; ++i) {
console.log(j);
}
// 7, 7, 7, 7, 7
for (const key in {a: 1, b: 2}) {
console.log(key);
}
// a, b
for (const value of [1,2,3,4,5]) {
console.log(value);
}
// 1, 2, 3, 4, 5
-
Best practices
- Don't use var
- Prefer const over let if not reassign
-
Data types
-
primitive type
- undefined
- null
- boolean
- number
- string
-
symbol
- newly introduced in ECMAScript 6
-
complex data type
- Object
-
The typeof operator
- let message = "some string";
console.log(typeof message); // "string"
console.log(typeof(message)); // "string"
- Operators
- Statements
- Functions