JavaScript¶
What is JavaScript¶
JavaScript is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.
Interpreted¶
The interpreter reads the source code and executes it directly. It does not require the compilation of the program into machine-code.
Just-in-time (JIT) compiled¶
The interpreter compiles the hot parts of the source code into machine-code and executes it directly. The rest of the program is interpreted.
First-class functions¶
Functions are treated like any other value. They can be stored in variables, passed as arguments to other functions, created within functions, and returned from functions.
https://developer.mozilla.org/en-US/docs/Web/JavaScript
JavaScript is a prototype-based, multi-paradigm, dynamic language, supporting object-oriented, imperative, and declarative (e.g. functional programming) styles.
Dynamic¶
Performs at runtime what static languages perform at compilation time (e.g. dynamic typing).
Prototype-based and object-oriented¶
Behavior reuse (and inheritence) is achieved by cloning and extending objects.
Imperative¶
Imperative programming is a programming paradigm that uses statements that change a program's state.
Declarative¶
Declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow.
https://developer.mozilla.org/en-US/docs/Web/JavaScript
ECMAScript¶
ECMAScript (or ES) is a specification created by ECMA International to standardize JavaScript.
Notes:
Birth
- 1994: Netscape Navigator is released, quickly becomes the most-used.
- Web pages can then only be static, so Netscape added a scripting language to their navigator: a language created by newly-hired Brendan Eich, similar syntax to Java, called LiveScript in its beta, and then renamed to JavaScript at its release.
- Invented by Brendan Eich in 1995. He was also the cofounder of Mozilla.
Standardization
- 1996, Netscape meets with ECMA to standardize JavaScript. Happens in 1997.
Adoption
- 1999: third major release comes out, ES3. Internet Explorer is the new best explorer
Asynchronicity
- 1999: AJAX (Asynchronous Javascript and XML) arrives in JS and is quickly adopted. Essentially decouples data communication with data presentation, allowing more dynamic web pages.
JSON
- 2009: ES5 comes out, JSON becomes standard
- JSON first showed up in 2001, informally specified in 2006, and then officially standardized in 2013.
ES6: 2015
ES7: 2016
etc
JavaScript on the server?¶
Not a modern idea:
- 1996: Microsoft and Netscape offered JS as a backend language.
- 1997: Rhino, a JS engine written in java.
- 2009: Ryan Dahl creates
node.js
, a JS environment for the server based on V8, an open source JS engine created in 2008 by Lars Bak for Chrome. - 2018: Ryan Dahl creates Deno, a new runtime for JavaScript and TypeScript based on V8 and Rust.
- 2019: Oracle releases the first stable version of GraalVM, making JavaScript a high performance language for the JVM, later integrated in their RDBMS through MLE.
Client-side and Server-side Programming¶
Today, JavaScript is commonly used in browsers (client-side), on servers (server-side), and at the edge (cloudflare, fastly, etc.).
ECMAScript 6 Support¶
https://kangax.github.io/compat-table/es6/
Eloquent JavaScript¶
https://eloquentjavascript.net/
JavaScript: The Good Parts¶
https://www.oreilly.com/library/view/javascript-the-good/9780596517748/
Foundations of JavaScript¶
Client-side JavaScript¶
Adding JavaScript to a Web page is as simple as adding a script
tag to the HTML document.
The src
attribute is used to specify the location of the JavaScript file.
The type
attribute is used to specify the type of the script. The default value is text/javascript
. The module
value is used to load a JavaScript module (ECMAScript 6).
The defer
attribute is used to defer the execution of the script until the page has been loaded.
The async
attribute is used to load the script asynchronously.
Server-side JavaScript¶
After installing nodejs, a REPL (Read-Eval-Print-Loop) can be obtained by typing the node command:
https://nodejs.org/api/repl.html
Get to know the REPL commands¶
.clear
- Reset the REPL context to an empty object and clears any multi-line expression currently being input.
.exit
- Close the I/O stream, causing the REPL to exit.
.help
- Show this list of special commands.
.save
- Save the current REPL session to a file: > .save ./file/to/save.js
.load
- Load a file into the current REPL session. > .load ./file/to/load.js
.editor
- Enter editor mode (
https://nodejs.org/api/repl.html#repl_repl_commands
JavaScript's Types¶
ECMAScript defines 7 primitive (Immutable) types for values:
Undefined
: Unique valueundefined
Number
: Real or integer number (e.g.3.14
,42
)Boolean
:true
orfalse
String
: Character sequence, whose literals begin and end with single or double quotes (e.g."HEIG-VD"
,'hello'
)BigInt
: Arbitrary-precision integers, whose literals end with ann
(e.g.9007199254740992n
)Symbol
: Globally unique values usable as identifiers or keys in objects (e.g.Symbol()
,Symbol("description")
)Null
: Unique valuenull
In a dynamic language you don't specify the type when you declare a variable and the type of a variable can change.
ECMAScript also defines a special mutable type called object for collections of properties (objects and array).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types
Notes:
The Symbol
data type is special.
Calling Symbol("description")
creates a symbol value with description "description"
. That value is guaranteed to be unique in the entire execution context (hence even across different libraries or modules). Therefore, two calls to Symbol("desc")
will return two different values.
It can be used anywhere an identifier or a key is expected, so for example an object car
(see next chapter) could have a property whose index is Symbol("model")
, rather than simply "model"
. This would ensure that this property does not get overridden by mistake by an inheritting class (see next chapter on OOP), for example.
Objects¶
An object in JavaScript is a mutable unordered collection of properties, each being
- A property key (either a string or a symbol)
- A value (any ECMAScript language value)
The syntax for creating an object is as follows.
Properties of an object can be accessed through the dot notation, or the bracket notation.
We will learn more about objects (and object-oriented programming in JS) in the next chapter.
Arrays¶
Arrays are a globally defined, resizable, list-like object. They can contain a mix of different data types.
Accessing items of a list can be done with square brackets. Items are zero-indexed. The length
property returns the array's length
Various useful methods exist on arrays for modifying them.
We will learn more about arrays in the next chapter about Object-oriented JavaScript.
typeof Operator¶
The typeof
operator is useful for determining the type of a variable or a value.
The operand can be of any type: - If the operand is a primitive value, typeof
returns a string indicating the type of the primitive value. - If the operand is an object, typeof
returns "object"
.
Notes:
Note that typeof null
returns "object"
. This could be considered a bug of the typeof
operator, as we have seen that null
is theoretically of type Null
.
Note also that an Array falls in the category of objects.
Regarding Array, we have seen that arrays are actually objects under the hood. See OOP chapter to understand why in detail.
Arithmetic Operators¶
An arithmetic operator takes numerical values (either literals or variables) as their operands and returns a single numerical value.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
String Operators¶
The concatenation operator (+) concatenates two string values together, returning another string that is the union of the two operand strings.
In practice, prefer template literals to concatenation.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
Assignment Operators¶
An assignment operator assigns a value to its left operand based on the value of its right operand.
JavaScript also has increment and decrement unary operators
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
Destructuring Assignment¶
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
Logical and Ternary Operators¶
Logical expressions are evaluated from left to right. JavaScript allows "short-circuit" evaluation.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
Notes:
Short-circuit evaluation allows JavaScript to bypass evaluation of the second term of a logical operation if the first one suffices to determine the result of the operation. This can happen in two cases:
a && b
:b
will not be evaluated ifa
isfalse
, since the result will befalse
regardless ofb
.a || b
:b
will not be evaluated ifa
istrue
, since the result will betrue
regardless ofb
.
Optional chaining (?.)¶
The optional chaining operator (?.) permits reading the value of a property located deep within a chain of connected objects without having to expressly validate that each reference in the chain is valid.
In this example, if we had omitted the ?
symbol, it would have failed with a TypeError: adventurer.dog is undefined
.
Introduced with ECMA2020.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
Comparison Operators¶
Comparison operators return a logical value based on whether the comparison is true.
Automatic type conversion is performed when comparing values of different types. It is at the root of many issues when using comparison operators.
Strict equality compares both the type and the value. It is recommended to use strict equality (===) and strict inequality (!==) operators.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators
Variable declaration statements¶
The var
statement declares a non-block-scoped variable, optionally initializing it to a value. Its scope is its current execution context, i.e. either the enclosing function or, if outside any function, global. It can be re-declared.
The let
statement declares a block-scoped local variable, optionally initializing it to a value. Its scope is the block in which it is declared.
The const
statement declares a block-scoped constant. The value of a constant cannot change through re-assignment, and it can't be redeclared.
A single statement can define multiple variables or constants: let one = 1, two = 2;
.
Notes:
The differences between var
and let
are important.
Scope¶
- The scope of a
var
is its enclosing function, or global. This means avar
declared in anif
block will still exist outside that block. - The scope of a
let
is its enclosing block, meaning alet
variable declared in anif
block will no longer exist otside that block.
Re-declaration¶
A var
can be re-declared, in which case the previous declaration is overridden. On the other hand, trying to re-declare a let
variable will result in an error.
Conditional Execution¶
In JavaScript, conditional execution is controlled by the if
statement.
Switch¶
Sometimes a switch looks better than an if...elseif...else
statement.
While and Do While¶
while and do while are used to loop until a condition is met.
For Loops¶
The classic for
statement is used to loop a given number of times over a block.
The for...in
statement iterates over the enumerable properties of an object.
The for...of
statement creates a loop iterating over iterable objects.
Notes:
Note that you can thus use for...in
on an array, which would iterate over the array's properties, rather than its items. Because of how arrays are implemented as objects in JavaScript, its properties are its indices, so the following code
would print 0
, 1
, 2
, 3
, 4
, and 5
, i.e. the indices of the array.
JavaScript Break and Continue¶
The break
statement terminates the current loop.
The continue
statement terminates the execution of the current iteration and continues the execution of the loop with the next iteration.
break
and continue
can also be used with labelled statements, but please don't.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
JavaScript Exceptions¶
In Javascript, runtime errors can be handled using the try...catch
statement.
Exceptions can be triggered using throw
and Error
:
Notes:
There are two types of errors in JavaScript: Runtime and Syntax errors. Because Syntax errors are thrown in the syntax checking phase, which occurs before the corresponding block is even entered, a try-catch block will not catch a syntax error. Only runtime errors, which are thrown when the block is being executed, are caught by try-catch blocks.
JavaScript Functions¶
A function is created with an expression that starts with the keyword function
and can be assigned to a regular variable. It can have parameters and may return
a value.
Declaration Notation¶
Arrow Notation¶
JavaScript Function Parameters¶
Function parameters can be made optional by specifying default values.
The default value is used if - that argument is not provided, or - undefined
is provided.
This means that optional parameters need not be last.
By default, the default value of a parameter is undefined
.
JavaScript Recursion¶
It is fine for a function to call itself.
.. as long as it does not overflow the call stack.
JavaScript Function Scopes¶
Definition: The scope of a variable is the part of the program (block or function) in which it exists and can be used.
-
var
variables: local to the function body, or global if not defined in a function. -
let
orconst
variables: local to the block in which they are declared. -
Function parameters: local to the function body. They are added to the call stack every time a function is called and freed when the function returns.
Higher-Order Functions¶
Higher-order functions allow us to abstract over actions, not just values. For example, we can have functions that create new functions.
https://eloquentjavascript.net/05_higher_order.html
JavaScript Closure¶
A closure is the combination of a function and the local scope within which that function was declared.
This is what it looks like when using a closure?
Regular Expressions¶
Regular Expressions¶
Regular expressions are patterns used to match and extract character combinations in strings.
It is useful for validating inputs, parsing files, extracting information from free text.
For instance, given the format for registration plates in Switzerland: - Validate that the given string is a valid registration plate - Extract all the registration plates listed in a unstructured text
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
Building Regular Expressions¶
The following notations can be used to define a regular expression in JavaScript. The description of the regular expression must be surrounded by "/
" symbols.
A regular expression is usually built with the following constructs:
- Character Classes (
.
,\s
,\d
, ...) that distinguish types of chararters (resp. any, whitespace or digit) - Character sets (
[A-Z]
,[a-z]
,[0-9]
,[abc]
, ...) that match any of the enclosed characters (resp. uppercase letters, lowercase letters, digits, and any ofa
,b
orc
) - Either operator (
x|y
) that match either the left or right handside values - Quantifiers (
*
,+
,?
,{n}
,{n,m}
) that indicate the number of times an expression matches - Boundaries (
^
,$
) that indicate the beginnings and endings of lines and words - Groups (
()
,(?<name>)
,(?:)
) that extracts and remember (or not) information from the input - Assertions (
x(?=y)
) that helps at defining conditional expressions
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
Fun with Flags¶
Regular expressions have optional flags that allow for functionality like global and case insensitive searching.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
Notes:
- A global regular expression is intended to be tested against all possible matches in a string, as opposed to consider the first match sufficient.
- A multiline regular expression is intended to be tested on a string with multiple lines. In particular, it indicates that the special
^
an$
symbols match the beginning and end of lines, rather than of the entire string.
Other flags exist, such as s
to allow the .
symbol to match newline characters or u
to treat the pattern as a sequence of unicode code points. See here for a full list.
Executing Regular Expressions¶
The following notations can be used to execute regular expressions.
In addition to matchAll
, a string comes with the match
, replace
, search
and split
methods.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
- Example of a regular expression that extracts the canton and the number of a Swiss registration plates.
- Example of a regular expression that extracts a list of Swiss registration plates from a free text.
Notes:
Javascript Arrays and Iterables¶
Arrays methods¶
Recall the Array object. Its prototype has many methods. Some of the useful ones are:
concat()
concatenates two or more arrays and returns a new array.join()
joins all elements of an array into a string.pop()
removes the last element from an array and returns that element.push()
adds one or more elements to the end of an array and returns the new length of the array.reverse()
reverses the order of the elements of an array.shift()
removes the first element from an array and returns that element.slice()
selects a part of an array, and returns it as a new array.sort()
sorts the elements of an array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Array's functional methods¶
The Array object also has some functional methods, which are:
forEach()
executes a provided function once for each array element.
map()
creates a new array with the results of calling a provided function on every element.
flatMap()
maps each element using a mapping function, and then flattens the resulting array by one level.
filter()
creates a new array with all elements that pass the test implemented by the provided function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Notes:
Flattenning an array by depth n
means replacing any sub-array it contains with the elements contained by that subarray, n
times. Note that a flat
method exists in Array.prototype
which does exactly that, meaning that flatMap
is equivalent to calling map
and then flat
.
reduce()
and reduceRight()
execute a reducer function on each element of the array, resulting in a single value.
every()
tests whether all elements in the array pass the test implemented by the provided function.
some()
tests whether some element in the array passes the test implemented by the provided function.
find()
and findIndex()
return the value (or its index, respectively) of the first element in the array that satisfies the provided testing function.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
Inverted Index¶
Given a list of documents, create an inverted index. An inverted index is a dictionary where each word is associated with a list of the document identifiers in which that word appears.
console.log(invertedIndex)
to prints the following Using the replace
, split
, filter
, map
, flatMap
, and reduce
methods
you should do something like this:
Iterators¶
Iterators are objects that provide a next()
method which returns an object with two properties:
value
: the next value in the iterator, anddone
: whether the last value has already been provided.
Iterables are objects that have a Symbol.iterator
method that returns an iterator over them.
Notes:
Recall: The for...of
loop requires its second operand to be an iterable.
Generators - Convenient iterators¶
Allows the definition of a function that can "return multiple times" with the yield
keyword:
function*
declares a generator, which is a type of iterator, not a function.yield
effectively pauses execution after returning its operand. On a next call to the iterator, it will resume execution.yield*
is followed by another generator or iterable object and delegates the generation to them until they are empty.
Notes:
Remarks¶
When used as a class method, since there is no function
keyword, the asterisk is put before the name :
Useful Built-in Iterables¶
The Map
and Set
objects are iterable and have a forEach
method.
The Map
object holds key-value pairs and remembers the original insertion order of the keys.
The Set
object lets you store unique values of any type.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Object