Lecture 13 Introduction to modern Javascript

JS Logo

What is Javascript?

The only client-side programming language that executes in the browser

What can Javascript do?

Famously designed in 10 days by Brendan Eich, a Netscape employee. Originally Mocha, gets renamed to LiveScript 5 months later and JavaScript 3 months after.

Javascript was a language that had…

…the functionality of Scheme
…the object orientation of Self
…and the syntax of Java

Scheme/LISP

SICP

I was under marketing orders to make it look like Java but not make it too big for its britches … [it] needed to be a silly little brother language.

Brendan Eich (source)

Java: Early syntactic influence


			statement1;
			statement2;
			statement3;
		

			if (condition) {
			statements
			}
		

			for (init; test; step) {
				statements
			}
		

			function name(arg1, arg2) {
				return value;
			}
		
- In fact, these particular syntactic aspects are not exclusive to (or even introduced with) Java, but are part of the general C-like syntax of many programming languages. - Fun fact: Semicolons are actually optional, and may be inserted by the browser if deemed missing (semicolon insertion). This is the cause of many headaches because missing semicolons change the meaning of your code without producing an error. There are linters like [ESLint](https://eslint.org/) to make sure you never forget semicolons.

Standards

Javascript on the server: Node.js

Javascript on the desktop: Electron

Javascript is the world's most popular programming language

Script tag

- This is how you run JS in a page. You may find older code without `type="module"` but that has certain quirks and does not allow you to include other scripts.

JS Topics

At first glance, everything seems normal

Braces for blocks, not whitespace

All of the following are functionally equivalent


			if (condition) {
				statement1;
			}
		

			if (condition) {statement1;}
		

		             if (condition)
			statement1;
		

			if (condition) statement1;
		

Braces for blocks, not whitespace

Are the following functionally equivalent?


			if (condition) {
				statement1;
				statement2;
			}
		

			if (condition) {statement1; statement2;}
		

			if (condition)
				statement1;
				statement2;
		

			if (condition) statement1; statement2;
		
It's a good practice to always use braces. Otherwise, it's very easy to get carried away by indentation when we add a second statement and not notice that it's not part of the block. Furthermore, while we could technically do everything on the same line, it's hard to scan, and less convenient for version control.

The Console

The console

Purpose

  • Inspect environment of current window
  • (distinct for each window/tab)
  • And modify it
  • Global variables defined in your code
  • Data logged to console by your code
  • DOM: document structure data

Special Variables and Functions

$('#id')
First DOM element matching CSS selector
$$('.class')
Array of all DOM elements matching selector
$0 - $4
Last 5 elements selected in elements panel
$_
Last evaluated expression

Writing to the console
Very useful for debugging!


			<script type="module">
			console.log("Hello world", 4 * 2 ** 3 + 10)
			console.log({firstName: "David", lastName: "Karger"})
			</script>
		

Let’s unpack this…

>
				4
				*
				2
					** 3
					+ 10
			
< 42

Let’s unpack this…

>
				$$("h1, h2, h3")
			
< [h1,
				h2,
				h3#general-information, ...]

Types (and coecion)

What if we had typed this instead?

4 * "2" ** 3 + 10
  1. 42
  2. TypeError: "2" is not a number
  3. "3210"
  4. NaN

What if we had typed this instead?

4 * 2 ** 3 + "10"
  1. 42
  2. TypeError: "10" is not a number
  3. "3210"
  4. NaN

Implicit type coercion

Read more about type coercion (very deep and advanced post):

Implicit coercion is a heuristic

Sometimes convenient

slider.step = (slider.max - slider.min)/10

Implicit coercion is a heuristic

Sometimes convenient


			if (new Date() - date < 60000) {
				console.log("Less than a minute ago")
			}
		

Implicit coercion is a heuristic

Often confusing

Code Result
2 * "5px"
[] + []
3 == "03"
"" - true
Was this fun? A lot more JS curiosities can be found at .

Escaping the heuristic

Code Result
Type conversion
4 * 2 ** 3 + Number("10")
Strict equality
3 === "03"
Number parsing
2 * parseFloat("5px")

Implicit coercion: booleans


			if (heading && heading.id) {
				// Heading is non-empty and has an id, linkify
				heading.innerHTML = `<a href="#${heading.id}">
					${heading.textContent}
				</a>`;
			}
		

What is the value of "Hello" && 0?

In JS, && and || do not (necessarily) return boolean
They are essentially conditional operators, like a ternary

Conditional expressions

JS expression Python expression
a ? b : c b if bool(a) else c
a && b b if bool(a) else b
a || b a if bool(a) else b

Truthy and falsy values

Variables and Constants

let declares a variable mondayLectures is an array of HTMLElement objects length is a property of all arrays, and returns (or sets) the number of items Brackets allow us to access individual items textContent is a property of all elements, and returns (or sets) the textual content Notice how the title of the first lecture changed!

Variables and constants


			// let declares a variable
			let r = 10;
		

			// const declares a constant
			const π = Math.PI;
		

Again, everything so far seems run-of-the-mill…

In older examples, you will also see var. Don't use it, there are many pitfalls with var that let avoids!

What do you expect to happen?


			let x = "Hello";
			x = 1;
			console.log(x);
		
  1. TypeError: Cannot assign Number to x. x is of type String.
  2. The console logs 1
  3. The console logs "Hello"

JS is dynamically typed: types are associated with values, not with variables

What do you expect to happen?


			let x;
			console.log(x);
		
  1. ReferenceError: x is not defined
  2. The console logs null
  3. The console logs undefined

What is undefined?

What do you expect to happen?


			const π = 3.1415926;
			π = 22 / 7;
			console.log(π);
		
  1. TypeError: Assignment to constant variable
  2. The console logs 3.1415926
  3. The console logs 3.142857143 (22/7)

What do you expect to happen?


			const squares = [1, 4, 9, 16];
			squares[4] = 25;
			console.log(squares);
		
  1. TypeError: Assignment to constant variable
  2. The console logs [1, 4, 9, 16]
  3. The console logs [1, 4, 9, 16, 25]

Constants hold a read-only reference to a value, but that value may be mutable
Why are constants useful?

Why are constants useful? It's an example of letting a programmer articulate an intention that the software can make sure they're following. This is the value of strong typing too. The program can warn you if you use a type you didn't intend to use. Similarly, the program can warn you if you assign to something you didn't plan to change. It indicates you made a mistake, either in the coding a mistake of intention.

Objects

Object literals


			let today = new Date();
			console.log(today.toLocaleString("en-GB", {
				day: "numeric",
				month: "long",
				year: "numeric",
				dayPeriod: "long"
			}));
		

Property access

These all result in the same object


			let user = {
				name: "Lea Verou",
				age: 34
			};
		

			let user = {
				name: "Lea Verou"
			};
			user.age = 34;
		

			let user = {};
			user["name"] = "Lea Verou";
			user["age"] = 34;
		

			let user = {
				"name": "Lea Verou",
				"age": 34,
				"hobbies": ["Coding", "cooking"]
			};
			delete user.hobbies;
		

What will happen here?


			let user = {
				name: "Lea Verou",
				age: 34
			};
			console.log(user.hobbies);
		

Any non-existent property, on any object, can be read and just returns undefined

What will be logged here?


			let user = {
				name: "Lea Verou",
				age: 34
			};
			user.age = undefined;
			console.log(user);
		

undefined can also be a legit property value. Setting a property to undefined does not delete it.

What will be logged here?


			let hobbies = ["Coding", "Cooking"];
			hobbies.user = "Lea Verou";
			console.log(hobbies.length, hobbies.user);
		

Arrays are also objects. Any object can have properties added to it at any point.

What will be logged here?


			let hobbies = ["Coding", "Cooking"];
			hobbies["1"] = "Dining";
			console.log(hobbies[1], hobbies["1"]);
		

Array indices are merely numerical properties

Scoping

What do you expect to happen?


			if (true) {
				let x = 1;
			}

			console.log(x);
		
  1. ReferenceError: x is not defined
  2. The console logs 1
  3. The console logs undefined

let (and const) are block-scoped
= only visible within the {...} they’re declared in

What do you expect to happen here?


			if (true) {
				let x = 1;
				log();
			}

			function log() {
				console.log(x);
			}
		
  1. ReferenceError: x is not defined
  2. ReferenceError: log is not defined
  3. The console logs 1
  4. The console logs undefined

JS uses lexical scope
= scope determined by syntax ({...}), not execution

Did you notice anything else?


			if (true) {
				let x = 1;
				log();
			}

			function log() {
				console.log(x);
			}
		
Notice that we were able to call the function before it was used. This is called hoisting and happens with function declarations like this one . There are other ways to declare a function, that do not hoist, which we will learn in the next few lectures.

Declarations are hoisted
= the function is available before it's declared

var declarations

Window and Global scope

Global and Module scope