Lecture overview¶
- HTML/CSS Review
- What is JavaScript?
- The JavaScript language
- features
- JavaScript in the web browser
- accessing the DOM
- manipulating the DOM
- user interaction: events and event listeners
- JavaScript syntax
- control structures
- loops
- functions
- JavaScript Objects
HTML/CSS review¶
HTML - structure¶
- DOM (Document Object Model)
- Hierarchical document structure
- Element tags
<body>
,<div>
,<h1>
,<span>
, etc. - Element attributes, e.g.
src
,href
,class
,id
- Elements can contain other elements
CSS - style and layout¶
- Selectors: used to specify scope of declaration blocks
- HTML structure dictates which selectors can be useful
- Style: color, size, image positioning, typography etc
- Layout
display: block
|inline
|inline-block
|flex
|grid
position: static
|relative
|absolute
|fixed
|sticky
top
,left
,right
,bottom
margin
,padding
align-items
,justify-content
(onflex
parent)
- Extra tip: learn
grid
layout at https://cssgridgarden.com/
Validating your HTML and CSS¶
What is JavaScript?¶
Why the confusing name?¶
Web scripting¶
- In 1995, Netscape wanted a way for their browser, Netscape Navigator, to display and interact with dynamic web pages.
- They were planning to use Scheme, a Lisp dialect, and hired Scheme enthusiast Brendan Eich to do it.
- A deal with Sun Microsystems saw the Java programming language integrated with Netscape's browser Navigator.
- Instead of Scheme Netscape management now requested something that "looks like Java" but is simpler, more light-weight and doesn't compete with Java (specifically, it couldn't have classes).
- Eich was given 10 days to create a functioning prototype, which was released with only small changes.
Eich's creation¶
- A curly-braces language that looks a bit like Java (on the surface).
- Has prototype-based object-orientation inspired by the Self programming language (in order to have OOP without classes).
- Was created in 10 days by a single developer.
- That developer was passionate about Scheme and had prepared for months to implement a Scheme interpreter.
- It was given the name JavaScript
- Because it was supposed to be the scripting alternative to using the "real" programming language Java.
- To ride the coat-tails of the now meteoric rise in Java's popularity.
To summarize¶
- JavaScript is not Java.
- JavaScript is not a subset of Java.
- JavaScript is not derived from Java (except in the most superficial sense).
- "Java" is not shorthand for JavaScript.
- JavaScript was not even designed to run on the JVM (but later JVM implementations exist, as for most high-profile languages).
- The name and superficial similarities in syntax are simply a result of office politics and marketing strategy at Netscape in 1995.
JavaScript features¶
- Interpreted
- Though techniques like JIT-compiling, hoisting, etc. give modern JS some features of compiled languages.
- Single-threaded
- Operations are executed one at a time in sequence with no native parallellization. Though this is less true now than for the first 20 years of JavaScript's existence.
- Multi-paradigm
- Object-oriented using prototyping, though classes are available since 2015.
- Functional, with first-class functions, anonymous functions, the option of constants, and higher-order built-ins like
map
,reduce
, andfilter
, although few built-in functions are pure functions.
Where is JavaScript used¶
- On web pages as "client-side scripting" – this is what we'll be doing in this course
- On servers as "server-side scripting" – e.g. using Node.js, Deno and frameworks built on them
- Browser extensions – e.g. for Google Chrome
- Mobile app development – e.g. using ReactNative
- Desktop app development – e.g. using Electron
JavaScript is JavaScript, is JavaScript?¶
- The language and syntax is the same regardless of where we use it.
- What JavaScript operates on, i.e. what API the code is interacting with, varies.
Google Chrome Extension¶
// Create a simple text notification:
let notification = webkitNotifications.createNotification('48.png', // icon url - can be relative
'Hello!', // notification title
'Lorem ipsum...' // notification body text
);
JavaScript for PDFs - annotation¶
/* The getAnnot method returns an Annotation object, an object that holds all
data of the annotation. This method takes two parameters, nPage (page number)
and cName (the name of the annot). For example, */
let a = this.getAnnot({ nPage: 2, cName: "myAnnot" });
if ( a != null ) {
console.println("This annot has type " + a.type);
if ( (a.type != "FileAttachment") || (a.type != "Sound") )
console.println("The comment of this annot is " + a.contents);
}
Get div
nodes from HTML DOM¶
let divs = document.getElementsByTagName('div');
for (let i = 0, div; div = divs[i]; i++) {
/* Process div in some way */
}
What can JavaScript do?
JavaScript can be used to¶
- Manipulate the DOM, i.e.
- Change DOM structure
- Change the ID of DOM nodes
- Change the classes of DOM nodes
- Change contents of DOM nodes
- Manipulate the CSS
- Add inline CSS to the DOM
- Change the contents of the stylesheet
- Capture web browser events
- changes to the web browser window (size, active/not active, URL etc)
- changes originating from input devices: mouse movement, keyboard key presses, single and multitouch events
Creating an interactive interface using HTML, CSS and JavaScript¶
- Use HTML to create the initial content.
- Use CSS to style and layout the content.
- Use JavaScript to
- Listen for specific web browser events on specific elements in the DOM.
- Change/Create elements in the DOM.
JavaScript today¶
- Language features
- DOM access and traversal using the WebAPI
- Event handling
The JavaScript language
Assignment 2: Codecademy exercises¶
- Codecademy exercises to practice your JavaScript.
- Codecademy exercises should be completed individually by each group member.
- You will not learn JavaScript during this lecture, you will get an overview and refresher of your prerequisite knowledge of programming.
- You will also have to practice on your own to internalize anything covered here.
A note on JavaScript code style¶
- Use
camelCase
for variable and function names.- Start variable and function names with a lower case letter.
- Use meaningful names for variable and function names.
- Put spaces around operators, i.e.
1 + 2
, not1+2
. - Indentation is for readability only but should use spaces, not tabs, and be consistent (2 is recommended, 4 is accepted).
- I'll generally be using 4 for readability on my slides.
- Terminate statements with semicolon
;
.
Types and variables¶
JavaScript is¶
- Dynamically typed
- Though type annotations and static type checking is an optional add-on (TypeScript).
- Lexically scoped
- Also called static scope. The body of a function is evaluated in the environment where the function is defined, not the environment where the function is called.
- Garbage collected
- I.e. like Python or Java, no manual allocation or de-allocation of memory.
Declaration and initalization of variables¶
- Variables are declared with the
let
keyword. - A variable does not have to be initialized (given an initial value) when declared.
- Differs from Python where declaration is implicit and happens the first time a variable is assigned a value.
- The first assignment to a variable initializes it (as long as it has been declared first).
- Referencing a variable declared with
let
before initialization causes an error. - Declaration and initialization can be written on one line.
In [1]:
let x;
x = "example";
let y = 5;
Out[1]:
"example"
Hoisting¶
- In Python, referencing a
let
-declared variable before it is initialized generates an error. - In JavaScript, variable declarations and function definitions are hoisted to the top of the scope before the code is run.
- However, variable initializations are not hoisted.
In [2]:
hoistExample1 = "new value";
let hoistExample1 = "initial value";
Stack trace: ReferenceError: Cannot access 'hoistExample1' before initialization at <anonymous>:1:36
In [3]:
hoistExample2 = "new value";
Stack trace: ReferenceError: hoistExample2 is not defined at <anonymous>:1:36
Constants¶
- The keyword
const
creates a constant, i.e. we are not allowed to change which value is referenced by the constant. - The referenced value itself is usually still mutable though.
- For example, if the value is an array:
In [4]:
const veggies = ["Tomato", "Lettuce", "Pepper"];
veggies.push("Carrot"); // Adds a new element (Carrot) to veggies
console.log(veggies)
[ "Tomato", "Lettuce", "Pepper", "Carrot" ]
Variables declared with var
¶
- The keyword
var
crates a variable with strange scope. - Before ES6, only
var
existed and it is still around in a lot of examples and legacy code so you need to know that it exists, but... - You should avoid
var
in this course (or any new code since ES6), so I won't provide examples.
Levels of nothing¶
- Trying to access a variable that has not been declared will result in a
ReferenceError
- When a variable is declared, but not initialized, it is
undefined
:
In [5]:
let value;
console.log(value)
undefined
- When a variable is declared and we want it to have a "non-value", we can set it to
null
:
In [ ]:
let value = null;
console.log(value)
Static typing¶
- Type checking is done before runtime, usually during compilation for compiled languages or by a static code analyser (or linter) for interpreted languages.
- Datatype of the value a variable refers to is not allowed to change during runtime.
- Most often, type has to be explicitly declared when the variable is declared (though not always, e.g. Haskell is an exception where type is inferred but inconsistency, i.e. inferring different types for the same variable at different points in the code, cause type errors).
- Examples: C, Java
int i = 1; // Note how we explicitly declare that i is an int
i = "hello";
-> error
Dynamic typing¶
- Type checking is done during runtime.
- Datatype of the value a variable refers to can change during runtime.
- Type usually isn't declared, though sometimes type annotations can be added (like in Python or JavaScript) and even enforced (MyPy/PyRight and TypeScript respectively).
- Examples: Python, JavaScript
let i = 1; // Note how we only declare a variable, not its type
i = "hello";
-> no problem
Is JavaScript "weakly" typed?¶
- There is no strict definition of "weak" (or, sometimes, "loose") typing.
- Sometimes erroneously used to refer to dynamic typing.
- Can usually be interpreted as "This language has a type system I don't like."
- (Yes, I've been guilty of this many times.)
JavaScript's "weak" typing¶
- Fairly many situations with implicit type conversion that would lead to errors in other languages.
- A result of JavaScript originally being aimed at "web designers, not programmers".
- (sighing and rolling of eyes is allowed, nay encouraged, here)
- Example:
In [6]:
let number_variable = 5;
let string_variable = "10";
let result = number_variable + string_variable ;
console.log(result);
510
Lexical scope¶
- Also called static scope (not to be confused with static type).
- "The body of a function is evaluated in the environment where the function is defined, not the environment where the function is called."
- I.e. variables are looked up where the code is written (lexically) not where the code is being run (usually called dynamic scope).
- Lexical scope is the norm today in most languages but can still trip you up.
In [7]:
let name = "Johan";
function printName() {
console.log("The name is " + name);
}
function printFullName() {
let name = "Johan Falkenjack";
printName();
}
printFullName();
The name is Johan
Scope chain¶
- JavaScript look up variables in the following order, equivalent to most languages with lexical scoping.
- Block Scope: Variables defined with
let
andconst
are limited to the block they are declared in, like loops or conditionals. - Nested Scope: Inner functions have access to variables in their parent functions.
- Local Scope: Variables defined inside a function or block, accessible only within that specific function or block.
- Global Scope: Variables defined outside any function or block, accessible anywhere in the program.
JavaScript in the browser
Connecting the script to the content¶
- Two ways of adding JavaScript to an HTML file
- Use the
<script>
tag and write inline JavaScript
<script>
console.log("Hello World");
</script>
- Use the
<script>
tag with the src attribute and reference a file with JavaScript code
<script src="helloworld.js"></script>
- The second approach is always preferable.
When is the JavaScript in the script tag run?¶
- The script is run when loaded.
- If the script depends on e.g. existing elements on the page, we need to load the script after those elements have been loaded.
- E.g.
- last inside the
<body>
element. - when an approriate event happens (we’ll get to this later)
- last inside the
Use defer to run JavaScript only after DOM created¶
- Adding the
defer
attribute to a script tag withsrc
attribute will wait until the DOM has been constructed to run the linked JavaScript file
<script src="script.js" defer>
HTML + JS Examples¶
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Execution in HTML</title>
</head>
<body>
<!-- Inline JavaScript -->
<script>
console.log("Inline JavaScript executed");
</script>
<!-- External JavaScript file -->
<script src="external-script.js"></script>
...
Multiple source files
<!DOCTYPE html>
<html lang="en">
<head>
<title>Classic JavaScript Import Example</title>
</head>
<body>
<h1>Hello, Classic JavaScript Import!</h1>
<script src="greet.js"></script>
<script src="use-greet.js"></script>
</body>
</html>
//greet.js
function sayHello() {
console.log('Hello from classic JavaScript import!');
}
// use-greet.js
sayHello();
Modules
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Modules Example</title>
</head>
<body>
<h1>Hello, JavaScript Modules!</h1>
<script type="module" src="use-module-example.js"></script>
</body>
</html>
// module-example.js
export function sayHello() {
console.log('Hello from the module!');
}
// use-module-example.js
import { sayHello } from './module-example.js';
sayHello();
JavaScript in the browser
JavaScript and the DOM¶
- More about the DOM
- What can we do with the DOM using JavaScript
- How can we use this to create interaction?
- What types of interaction - input/output - can we use in a web browser
- show/hide
- create/destroy
- move, position
- change shape, color
- click, drag, drop - elements on page and files from the computer
- type on keyboard
- images, movies, animations
Accessing the DOM tree¶
- Elements
- using querySelectors - use CSS selector syntax
- getElementsByTag
- getElementsByClass
- getElementById
- accessing an element’s relatives
- Text
- get an element’s text content
- using innerHTML
- Attributes
- get an element’s attribute nodes
- get an element’s specific attribute value
Accessing elements¶
The "old" way¶
- Both return a
HTMLCollection
object.
document.getElementsByTagName("tagname")
document.getElementsByClassName("classname")
- Returns an
Element
object.
document.getElementById("elementid")
- Can also be run on an element, e.g.
let mainMenu = document.getElementById("main-menu");
// get all li elements in #main-menu
let menuItems = mainMenu.getElementsByTag("li");
Newer query selectors¶
- We can use selectors that follow the CSS selector syntax.
- Using
querySelector
returns anElement
object, if the selector matches multiple element, the first element matching the query is returned.
document.querySelector("#elementid")
- Meanwhile,
querySelectorAll
returns a staticNodeList
object
document.querySelectorAll(".classname")
Element relatives¶
// get the first element from a selector result
let myElement = document.querySelector(".box p");
// get an elements relatives
myElement.firstElementChild;
myElement.lastElementChild;
myElement.parentElement;
myElement.nextElementSibling;
myElement.previousElementSibling;
Accessing elements¶
// get a NodeList of elements using a selector query
myElements = document.querySelectorAll("div p");
// get a live HTMLCollection of elements of a specified type
myElements = document.getElementsByTagName("a");
// Elements in NodeLists and HTMLCollections can be accessed
// using an index.
Should I use getElements*
or querySelectorAll
?¶
- It will depend on use case.
document.querySelectorAll("p")
returns a static, non-liveNodeList
of all nodes (including text and attribute nodes).document.getElementsByTagName("p")
returns a liveHTMLCollection
only containing elements.- If a new paragraph is added to the DOM:
- the "live"
HTMLCollection
automatically include the new element - the static
NodeList
will not, you will have to calldocument.querySelectorAll("p")
again
- the "live"
- Note: Not all
NodeLists
are static but the onesquerySelectorAll
returns are. - https://www.freecodecamp.org/news/dom-manipulation-htmlcollection-vs-nodelist/
Accessing element content¶
// get all HTML inside an element
allHTML = element.innerHTML;
// we can also change the inner HTML
element.innerHTML = "<img src='cat.jpg'>"
// just get the text content of an element
theText = element.textContent;
Accessing attributes¶
// array access to an element's attributes
theAttributes = element.attributes;
// get the value of an element's attribute
anAttribute = element.getAttribute("attributeName");
Editing the DOM tree
Change innerHTML and set an attribute value¶
// set inner HTML of an element
element.innerHTML = "new inner HTML";
// set the value of an element's attribute
element.setAttribute("attribute name", "attribute value");
Creating new nodes in the DOM tree
Create an element node¶
// create an h1 element
heading = document.createElement("h1");
// create a paragraph element
paragraph = document.createElement("p");
Create text nodes¶
- Any text inside a tag, e.g.
<p>text</p>
is a text node. We can add multiple text nodes to a element.
// create heading text
headingText = document.createTextNode("Heading 1");
// create paragraph text
paragraphText = document.createTextNode("Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam, rem, adipisci, iste nisi vel quibusdam nulla tenetur repudiandae possimus maiores inventore doloremque asperiores aut omnis cum et harum provident suscipit!");
Add text nodes to elements¶
// create an h1 element
heading = document.createElement("h1");
// create a paragraph element
paragraph = document.createElement("p");
// create heading text
headingText = document.createTextNode("Heading 1");
// create paragraph text
paragraphText = document.createTextNode("Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam, rem, adipisci, iste nisi vel quibusdam nulla tenetur repudiandae possimus maiores inventore doloremque asperiores aut omnis cum et harum provident suscipit!");
// add text to heading and paragraph
heading.appendChild(headingText);
paragraph.appendChild(paragraphText);
Appending and inserting elements¶
// append paragraph to body, append always places an element last
body = document.getElementsByTagName("body")[0];
body.appendChild(paragraph);
// insert an element at a specific position
bodyNodes = body.childNodes;
body.insertBefore(bodyNodes[0], heading);
Changing the CSS for an element
Inline styles vs Stylesheet rules¶
- Inline styles are specified using the style attribute
- Example
<div class="box" style="border: 1px solid green;"></div>
- As mentioned; Do not use the style-attribute in your HTML files.
- Why? Specificity (see https://specifishity.com/)
- Overrides most CSS rules.
- Creates a tight coupling between content and style, i.e. makes it harder to specify style separately.
- However, if necessary, we can manipulate the style-attribute using JavaScript.
Set an element’s style using JavaScript¶
// grab the first heading
heading = document.getElementsByTagName("h1")[0]
// change the font-family property of the heading
// note that properties with a dash ('-') are camelCased
heading.style.fontFamily = "Times"
- While not as taboo as manually styling using the style-attribute in HTML, this approach should generally be avoided.
Manipulating style with class¶
// grab the first heading
heading = document.getElementsByTagName("h1")[0]
// set a class
heading.classList.add("maintitle");
// remove a class
heading.classList.remove("fancy");
- This is the preferred way of changing the style of an element using JavaScript.
- The JavaScript only changes the class, and any styling is written as rules in the CSS.
Functions in JavaScript¶
Functions¶
- function declaration: declare named function
- function expressions: create function objects
- regular function expressions
- arrow function expressions (ES6)
- Use of function expression as a value = anonymous function
- Use the
return
keyword to return a value (except in arrow one-liners)
Function declaration¶
In [ ]:
// function declaration, create a named function
function helloWorld() {
console.log("hello world");
}
helloWorld();
In [ ]:
// function declaration with parameter
function greeting(name) {
console.log("hello " + name);
}
greeting("Charlie");
Function expression¶
In [ ]:
// defining an anonymous function, and keeping a reference to
// its function object
const f1 = function() {
console.log("Anonymous hello world");
}
f1();
In [ ]:
// function expression with a parameter
const f2 = function(somearg) {
console.log(somearg);
}
f2("Very secret message.")
In [ ]:
// referencing the function object of a named function
let hello = helloWorld;
hello();
Arrow functions¶
In [ ]:
const f3 = () => {
console.log("This is also a function.");
}
f3();
In [ ]:
const f4 = (anotherarg) => {
console.log(anotherarg);
}
f4("Another secret message!")
Arrow one-liners¶
In [ ]:
let add1_oneliner = (value) => {return value + 1}
console.log(add1_oneliner(4))
- Curly braces can be omitted in which case return is implicit.
In [ ]:
let add1_oneliner = (value) => value + 1
console.log(add1_oneliner(2))
- Parentheses can be omitted around single parameters.
In [ ]:
let add1_oneliner = value => value+1
console.log(add1_oneliner(7))
Function declaration, function expression, or arrow function?¶
- Only functions created using function declaration are hoisted.
- Only expressions (though both traditional function expressions and arrow expressions) can create anonymous functions.
- Only expressions (again, both types) can be invoked directly, creating Immediately Invoked Function Expressions (IIFEs).
In [ ]:
(() => {
console.log('This is printed despite the function not even being assigned a name or passed to a function.')
})()
User interaction - event handling
Elements have event handlers¶
- When an event is triggered in the context of an element, its event handlers are triggered
- Event examples
- when a mouse enters the area of an element
- when a mouse leaves the area of an element
- when the mouse is clicked on an element
- when a form field is given focus
Event handling¶
- Typical mouse interaction
onmouseover
onmouseout
onclick
- Typical form interaction
onfocus
onblur
onsubmit
Event handling in general¶
- Observer design pattern.
- A subject has a set of observers and methods to add and remove observers.
- The state of the subject changes by its
setState
-method being called. - At the end of the
setState
method, the subjectsnotifyObservers
-method is invoked. - The
notifyObservers
-method informs each of the subject's observers that a state change has taken place by calling theirupdate
-method. - Each observer's
update
-method calls their subject'sgetState
-method to get the subject's new state and change their behavior accordingly.
Observer pattern (simplified)¶
Event handling in web browsers¶
- Two possible ways
- Set the event handler property of element to the function to call when the event occurs
- These are the
onX
properties (onclick
,onmousedown
, etc.) - Just add "on" to the name of the event
- These are the
- Use
.addEventListener()
and.removeEventListener()
Using event handler properties¶
- We can set an element's event property to
- a named function object or
- an anonymous function object
- Example of event handler properties
element.onkeydown
element.onkeyup
element.onmousedown
element.onmouseout
- Only one event handler can be specified
Using the event handler property¶
// using an anonymous function
element.onclick = function(event) {
alert("Hello World");
};
// using an arrow expression
element.onclick = (event) => {
alert("Hello World");
}
// using a function object
function hello(event) {
alert("Hello World!");
}
element.onclick = hello;
Adding an event handler as an event listener¶
- We can use the
element.addEventListener()
method to add an event handler for a specific type of event - We specify the event type and the listener function, e.g.
element.addEventListener("keydown", keyhandler)
- Multiple listeners can be added to the same element.
Using .addEventListener()
¶
// using an anonymous function
element.addEventListener('click', function(event) {
alert("Hello World");
});
// using an arrow expression
element.addEventListener('click',(event) => {
alert("Hello World");
});
// using a function object
function hello(event) {
alert("Hello World!");
}
element.addEventListener('click', hello);
Event objects¶
- Event handler functions recieve an
Event
object that contains information about the event. - The kind of event decides what event type is sent
- All events have
Event.target
: reference to origin of event
- MouseEvents have e.g.
MouseEvent.screenX
,MouseEvent.screenY
: X and Y coordinates of the mouse
- See https://developer.mozilla.org/en-US/docs/Web/API/Event#interfaces_based_on_event
DOM being loaded is an event too
<!DOCTYPE html>
<html lang="en">
<head>
<title>Delayed JavaScript Execution</title>
<script type="module" src="delay.js">
</script>
</head>
<body>
<p id="displayContentHere"></p>
</body>
</html>
document.addEventListener("DOMContentLoaded",
(event) => {
let contentParagraph = document.querySelector("#displayContentHere")
contentParagraph.textContent = "This paragraph got its content only after DOM was loaded even though the .js file was loaded without defer.";
})
Simple assignment¶
- Uses the
=
operator like Python, Java, C, etc.- Requires that a variable be declared first but allows declaration and initialization on one line.
In [ ]:
let x = 1;
console.log("Value of x:", x.toString())
Augmented assignment¶
- Combines an arithmetic operation with assignment, e.g.
a += b
(addition assignment),a /= b
(division assignment),a %= b
(remainder assignment), etc.- Requires that a variable be initialized first.
- Essentially a shorthand for
a = a + b
In [ ]:
let y = 10;
x += y;
console.log("Value of x:", x.toString())
Increment and decrement operators¶
- Increments (or decrements) by 1 and returns the value before or after the increment.
- Whether it returns the value before or after increment (or decrement) depends on whether the operator is prefixed or postfixed.
- If postfixed (
x++
) it returns the value before the increment takes place. If prefixed (++x
) it returns the incremented value.
- If postfixed (
In [ ]:
let x = 5;
let before = x
let returned = x++
let after = x
console.log("Value before:", before.toString());
console.log("Value returned:", returned.toString());
console.log("Value after:", after.toString());
Datatypes¶
Datatypes¶
- Common datatypes
Boolean
Number
String
Array
Objects
- Note: Lots more when we have access to the WebAPI
Numbers and operators¶
- All numbers in JavaScript are stored as floating point numbers in the
Number
datatype.- Except integer values that are simply too large, which have their own type
BigInt
(BigInt
literals are written as an integer followed byn
, e.g.9007199254740991n
).
- Except integer values that are simply too large, which have their own type
- Other than that, arithmetic works as in e.g. Python or Java.
In [ ]:
let a = 3;
let b = 2.0;
console.log(a+b);
console.log(a-b);
console.log(a/b);
console.log(a*b);
JavaScript has two boolean values
false
andtrue
- The following evaluate to
false
, all other values evaluate totrue
:false
,null
,undefined
,0
(zero),-0
(minus zero),0n
(BigInt
zero),NaN
""
,''
,``
(empty string)
- Note that the empty
Array
does not evaluate tofalse
the way the equivalent value does in many other languages, e.g. Python.- This is because
Array
is just a special case ofObject
and allObject
-values evaluate totrue
. - (This might be one of those this-was-created-in-10-days-gimme-a-break issues, or possibly a Scheme-is-actually-also-insane-and-interpret-the-empty-list-as-true issue. Or I'm just biased and this is actually fine.)
- This is because
Strings¶
- Like in Python, strings are immutable.
- I.e. any concatenation, replacement, slice, etc. creates a new string object.
In [ ]:
let a = "Hello";
let b = "World!";
console.log(a + " " + b);
console.log(a, b);
In [ ]:
// length of string
console.log(a.length);
In [ ]:
console.log(a.replace("l", "j"));
console.log(b.startsWith("Wo"));
Arrays¶
- An array in JavaScript is superficially similar to the list in Python.
- We can create a new, empty array in different ways, and we can use 0-based indexing to access elements.
In [ ]:
let myArray1 = new Array();
let myArray2 = Array();
let myArray3 = [];
// we can fill an array when initializing it
let myArray4 = [1, 2, "hello"];
console.log(myArray4)
console.log(myArray4[0])
- But if we start scratching the surface, JavaScript's
Array
is actually quite different from Python's list.- E.g. we can set any position in an array, empty spots will be undefined
In [ ]:
myArray4[5] = "what!";
console.log(myArray4)
More on Array
¶
In [ ]:
let myArray = [1, 2, "hello", "world"]
console.log("Length of array:", myArray.length)
console.log("Pushing adds an element to end of array and returns the new length of the array:", myArray.push("yay"))
console.log("Popping removes and returns the last element of the array:", myArray.pop())
Objects¶
- JavaScript is an object oriented language.
- However: based on prototypes, rather than classes
- Though ES6 introduced class declaration syntax, the dev community is split on when, or even whether, these should be used.
- Objects have properties.
- Properties are accessed using dot notation:
object.property
- Properties can also be accessed using square bracket notation:
object["property name"]
- Objects can also have functions that can behave as methods.
- Functions in objects are called using dot notation:
object.function()
Object example¶
In [1]:
let image = {
filename: "cat1.jpg",
sayHello: function() {
console.log("Hello!");
}
}
console.log(image.filename);
image.sayHello();
cat1.jpg Hello!
Conditionals, comparisons and logical operators¶
Conditional statements¶
if (a == b) {
statement;
statement;
} else if (a == c) {
statement;
statement;
} else {
statement;
statement;
}
Comparison operators¶
- equal value (with type conversion):
==
- equal value and datatype (no type conversion):
===
- less than:
<
- less than or equal:
<=
- greater than:
>
- greater than or equal:
>=
- different value:
!=
- different value or different type:
!==
In [ ]:
console.log(1=="1");
console.log(1==="1");
Some weird (in)equalities in JavaScript¶
In [ ]:
console.log([] == 0)
console.log(Boolean([]) == Boolean(0))
In [ ]:
console.log(null > 0)
console.log(null == 0)
console.log(null >= 0)
In [ ]:
console.log(false == undefined)
console.log(false == null)
console.log(null == undefined)
In [ ]:
console.log(0 == '')
console.log(0 == '0')
console.log('' == '0')
Conclusion: Use ===
, not ==
¶
Logical operators¶
- not:
!
- and:
&&
- or:
||
- We can do weird things with these as well:
In [ ]:
console.log([] == ![])
Loops¶
Loops¶
while
do ... while
for
for ... in
for ... of
break
andcontinue
The while loop - while this is true, do this¶
- Works like most other
while
-loops you are likely to have experienced.
while (condition) {
//statement
//...
}
In [ ]:
let x = 5;
while (x > 0) {
console.log("x: " + x--)
}
The do while loop - do this, if this is true, loop¶
do {
//statements
//...
} while (condition);
- The loop body will always execute at least once. Very useful!
In [ ]:
let x = 5;
do {
console.log("x: " + x--)
} while (false)
C-style for loop - a while
loop with bells and whistles¶
for (<loop variable declaration and initialization>; <while-like condition>; <compute next value>) {
// statements
// ...
}
In [ ]:
for(let x = 5; x>0; x--) {
console.log("x: " + x);
}
for ... in
¶
- iterate over enumerable property in object
- "the keys" of an
Object
- the indexes of and
Array
- "the keys" of an
for(property in object) {
// statements
}
In [ ]:
let myArray = ["value 1", "value 2"]
for(let v in myArray) {
console.log("index: " + v);
}
for ... of
¶
- iterate over iterable object
- "the values" of an
Object
- the elements of an
Array
- "the values" of an
for(variable of object) {
// statements
}
In [ ]:
let myArray = ["value 1", "value 2"]
for(let e of myArray) {
console.log("value: " + e);
}
As in e.g. Python, we can break and continue¶
break
: abort current loopcontinue
: skip the rest of the current iteration and move to the next iteration
FYI¶
- Other ways of iterating can be provided by the different datatypes, e.g.
.forEach()
method inArray
andNodeList
objects
- The classic
map
,filter
, andreduce
trifecta are also available.