The Complete JavaScript Course 2024 Notes

Table of Contents

These notes are were taken and compiled by Aleks Ozolins.

Section 1: Welcome, Welcome, Welcome

Section 2: JavaScript Fundamentals - Part 1

Setting Up Our Code Editor

  • Jonas recommends VSCode… I will see if I can do this with Emacs.
  • Skipped the section on theme and VSCode settings because it doesn't apply in the moment.

Hello World and The Console

  • Hit Command + Option + J to open the Developer Tools in Chrome/Mac
  • That opens the Console
  • You can also right click and then click Inspect
  • Or View Menu > Developer > Console

In the console we can write:

alert("Hello World")

And then hit Return to evaluate it.

Or this:

let js = 'amazing'
if (js === 'amazing') alert('JavaScript is FUN!')

You can also use the console as a calculator.

A Brief Introduction to JavaScript

JavaScript is a high-level, object-oriented, multi-paradigm programming language.

What is the role that JS plays in web development?

There are 3 core technologies in the web:

  1. HTML
    • Responsible for the content of the page
    • Represents the noun <p
  2. CSS
    • Responsible for the presentation of that content
    • Represents the adjective p {color: red}
  3. JS
    • Programming language of the internet. Use it to manipulate content, load data from servers, build apps in the browser, etc.
    • Represents the verb p.hide();

JS Has Frameworks:

  • React
  • Vue

JS can run on servers:

  • node.js

You can use JS to build phone apps too:

  • React Native
  • Ionic

And desktop apps:

  • Electron

JS Releases

ES2015 or ES6 was a huge release. There is a new release every year. Starting from ES6 or ES2015, that's considered modern JS.

Linking a JS File

  • To start, we always need an HTML document.
  • In HTML, we need a script tag where we can write JS

You can use the <script> tag inline in an HTML file to make an 'inline script'. That works fine, but it's bad for separating the web content from the JS: See: file:///home/aleksozolins/repos/complete-javascript-course-master/01-Fundamentals-Part-1/starter/index-new.html

You can also put the JS into a script file instead:

We usually do this at the end of the <body> tag. See: file:///home/aleksozolins/repos/complete-javascript-course-master/01-Fundamentals-Part-1/starter/index-new-1.html

<body>
  <h1>JavaScript Fundamentals – Part 1</h1>
  <script src="script.js"></script>
</body>

Values and Variables

'Jonas' is a value. 65 is a value.

If we want to log it to the console:

  • console.log("Jonas");

A value is the smallest unit of information in JS. We can store values in variables:

let firstName = "Jonas";

We declared the variable firstName and assigned a value "Jonas"

Conventions and rules for naming variables

  • Camel Case = firstName or firstNamePerson (this is the standard in the JS world)
  • firstname (popular in Ruby)

There are some hard rules too:

  • A variable name cannot start with a number (Invalid or unexpected token error)
  • Variable names can only contain numbers, letters, underscores, or the $ sign.
  • A variable can't be named a reserved JS keyword like new or function but $function would be ok
  • Naming a variable name can sometimes lead to issues
  • Don't start a variable name with an uppercase letter. This is not illegal but it's a convention.
  • Variables in uppercase are reserved for constants that will never change like PI
  • Make sure variable names are descriptive like myFirstJob or myCurrentJob

Data Types

In JS every value is either an Object, or a Primitive.

  • Object = like a JS object
  • Primitive - like a value like 'Jonas' or 30

For now, we'll focus on primitive data types:

  • Number: A floating point number like 23. It's the same as 23.0
  • Strings: A sequence of characters used for text like 'Jonas'
  • Boolean: can only be true or false
  • Undefined: Value taken by a variable that is not yet defined. Like 'let children'. Means 'empty value'
  • Null: Also means 'empty value'
  • Symbol: Value is unique and cannot be changed (not useful for now)
  • BigInt: Larger integers than the Number type can hold

Those are the 7 primitave data types in JS.

JS has a feature called dynamic typing. You do not have to define the data type of any variable you declare. It is automatically determined. The value has a type… not the variable.

So variable x can initially be a number, and then later a string. This can be useful, but can sometimes cause bugs.

Code Commenting:

// This is a comment

You can comment out code too.

/*
This is a multiline comment
blah
*/

You can store booleans in variables:

let javascriptIsFun = true;
console.log(javascriptIsFun);

You can use the typeof operator to see what type of value it is.

let x = true;
console.log(typeof x);
boolean

You can change the type of a variable:

let x = 69;
console.log(typeof x);
x = 'Jonas';
console.log(typeof x);
number
string

An example of undefined:

let x;
console.log(x);
console.log(typeof x);
undefined
undefined

Above, the value of the variable is both the value and the type of the value.

Here's an interesting case – this is a BUG!

console.log(typeof null);
object

It should return null and not object

let, const, and var

Up until this point, we've used let to declare variables.

let and const are modern JS. var is the old way of declaring variables.

Use the let keyword to declare variables that might change later.

let age = 30;
age = 31;

In technical terms, we reassign the value or we mutate the variable.

We use const to declare variables that are not supposed to change in the future.

const birthYear = 1981;
birthYear = 1990;

This produces an error! const should be used for immutable variables.

We also cannot declare empty variables with const.

Use const by default and use let if you know the variable has to change.

It's a good practice to have as little mutation as possible. By default use const.

Regarding the var keyword, it's old and should be avoided. It is used for legacy reasons.

var works pretty much like let but below the surface they are actually pretty different.

You don't need to use let or const to declare a variable but you should always properly declare a variable because it can cause scoping issues.

Basic Operators

An operator allows us to transform or combine values. There are mathematical, comparison, logical, assignment operators, etc.

Mathematical operators:

The minus operator:

const now = 2024
const ageAleks = now - 1981;
const ageAnnika = now - 2024;
console.log(ageAleks, ageAnnika);
43 0

Other mathematical operators

  • * for multiply
  • / for division
  • * for exponentiation (2 * 3) = 2 to the power of 3 which is 2 * 2 * 2

We can use the + operator to join strings

const firstName = 'Aleks';
const lastName = 'Ozolins';
console.log(firstName + ' ' + lastName);
Aleks Ozolins

typeof is an operator too by the way.

Then there are assignment operators like the = sign

let x = 10 + 5
// in this case the = is an assignment operator
// 10 + 5 is done first, then the value is assigned to x

Another is +=

let x = 10 + 5;
x += 10; // This means x = x + 10
console.log(x);
25

There is also *= and /=

There is also ++ and –

let x = 10 + 5;
x ++; // This means x = x + 1
console.log(x);
16

Comparison Operators

const ageAleks = 42;
const ageAnnika = 0;
console.log(ageAleks > ageAnnika);
true

There is >= and <= as well

const ageAleks = 42;
const ageAnnika = 18;
console.log(ageAnnika >=18);
true

Usually we would store these results in variables and not log them directly to the console…

Operator Precedence

const now = 2037;
const ageJonas = now - 1991;
const ageSarah = now - 2018;
console.log(now - 1991 > now - 2018);

true

Question: Why does the above work? Why does JS evaluate on the left side of > and the right side of > and then compare them.

See the table here (you have to scroll down): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence

Usually all the math operators are executed before comparison operators.

Most happen left to right but assignment happens right to left:

let x, y;
x = y = 25 - 10 - 5 // this is evaluated right to left (but the subtraction is done left to right)
console.log(x, y)
10 10

Grouping has the highest precedence. Grouping uses ( )

const ageAleks = 42;
const ageAnnika = 18;
const averageAge = (ageAleks + ageAnnika) / 2; // we need the parens to make this work
console.log(ageAleks, ageAnnika, averageAge);
42 18 30

Coding Challenge #1

const massMark = 78;
const heightMark = 1.69;
const massJohn = 92;
const heightJohn = 1.95;
const BMIMark = massMark / (heightMark * heightMark)
const BMIJohn = massJohn / (heightJohn * heightJohn)
console.log("Mark's BMI is" + ' ' + BMIMark + ' ' + "while John's BMI is" + ' ' + BMIJohn + '.')
const markHigherBMI = BMIMark > BMIJohn
console.log("Is Mark's BMI higher than John's?" + ' ' + markHigherBMI)
Mark's BMI is 27.309968138370508 while John's BMI is 24.194608809993426.
Is Mark's BMI higher than John's? true

Strings and Template Literals

const firstName = "Aleks";
const job = "Support";
const birthYear = 1982;
const aleks = "I'm " + firstName + ". I was born in " + birthYear + ' and my job is ' + job + '.';
console.log(aleks);
I'm Aleks. I was born in 1982 and my job is Support.

With Template Literals, we can write a string in a more normal way, and insert the variables directly into the string.

const firstName = "Aleks";
const job = "Support";
const birthYear = 1981;
const aleksNew = `My name is ${firstName} and I was born in ${birthYear} and my job is ${job} and also my birthyear minus 2 years is ${birthYear -2}`;
console.log(aleksNew);
My name is Aleks and I was born in 1981 and my job is Support and also my birthyear minus 2 years is 1979

Notice we used backticks! You can also use backticks for any regular string.

Technically you can write any JS within the curly braces as we did above.

This is one of the most used ES6 features.

Choice: If you want, you can just use backticks for all strings.

Another great use of template literals is creating multi-line strings:

This is the old way:

console.log('String with \n\
multiple \n\
lines');
String with 
multiple 
lines

But this is better. Use the backticks!

console.log(`String
with
multiple
lines`);
String
with
multiple
lines

Taking Decisions: if / else Statements

Let's say we want to write a program to check if a person can get a driver's license. This is called an if/else control structure because it allows us to have control over how our code is executed.

const age = 16; // Play with this!

if (age >= 18) {
  console.log('You can get driving license!');
} else {
  console.log(`In ${18 - age} years, you can get your driving license!`);
}

In 2 years, you can get your driving license!

Another example:

Note that because we define the variable century within the if code block, it's not available outside… so we need to declare it outside the block.

const birthYear = 1981;
let century;
if (birthYear <= 2000) {
  century = `20th`;
} else {
  century = `21st`;
}

console.log(`You were born in the ${century} century.`)
You were born in the 20th century.

Coding Challenge #2

const massMark = 78;
const heightMark = 1.69;
const massJohn = 92;
const heightJohn = 1.95;

const BMIMark = massMark / (heightMark * heightMark);
const BMIJohn = massJohn / (heightJohn * heightJohn);
console.log(BMIMark, BMIJohn);

if (BMIMark > BMIJohn) {
  console.log(`Mark's BMI (${BMIMark}) is higher than John's (${BMIJohn})!`);
} else {
  console.log(`John's BMI (${BMIJohn}) is higher than Mark's (${BMIMark})!`);
}
27.309968138370508 24.194608809993426
Mark's BMI (27.309968138370508) is higher than John's (24.194608809993426)!

Type Conversion and Coercion

We mean converting a string to a number or a number into a Boolean, etc.

  • Type conversion is when we manually convert from one to another.
  • Type coercion is when JS automatically changes types for us.

Type Conversion

const inputYear = '1991'; // It's a string
console.log(inputYear + 18); // It gets concatenated

console.log(Number(inputYear) + 18); // We used the Number function to convert it to a number.
199118
2009

Note that the original variable is still a string.

What if we try to convert something that can't be converted to a number.

console.log(Number('Jonas'));
NaN

JS gives us Nan (not a number) in this situation.

Weirdly though, typeof for NaN is number.

We can also convert numbers to strings:

console.log(String(23), 23);
23 23

The first one above is a string. The second is a number.

JS cannot convert something to unefined or null.

Booleans behave in a special way.

Type Coercion

JS will convert values behind the scenes.

console.log('I am ' + 23 + ' years old');
I am 23 years old

In the case above, JS converted the number 23 to a string. The plus operator converted it. The same thing happens in template literale.

We do not have to do:

console.log('I am ' + (String(23)) + ' years old')
I am 23 years old

Strings canbe converted to numbers as well. This happens withe minus operator.

console.log('23' - '10' - 3);
10

So, with the plus operator, numbers can be converted to strings, and with the minus operator, strings can be converted to numbers.

But, if we try to convert strings to numbers with the + operator, that won't work:

console.log('23' + 10);
2310

This is an important distinction!

The * and / operator will also convert strings to number.

Here's a cool example:

let n = '1' + 1;
n = n - 1;
console.log(n);
10

So on line 1, it was converted to strings, but on line 2, it was converted to nubmers.

Another example:

console.log(2+3+4+'5');
95

Because it's being evaluated left to right, it adds numbers first, but then converts everything to string and concatenates.

Many people do not like type coercion and think it's a bad practice to rely on it. But Jonas thinks it's good for code. Embrace it in your code.

Truthy and Falsy Values

Falsy values are values that are not exactly false, but will become false when we convert them into a boolean. Here are the 5 falsy values:

Falsy values:

  • 0
  • ''
  • undefined
  • null
  • NaN

Truthy values are values that will become true. All other values are truthy.

console.log(Boolean(0));
console.log(Boolean(undefined));
console.log(Boolean('Aleks'));
console.log(Boolean({})); // an empty object
console.log(Boolean('')); // an empty string is falsy
false
false
true
true
false

You'll never really use the Boolean function. The conversion to Boolean is always implicit because type coercion is happening behind the scenes. When does JS convert values to boolean?

When does JS convert values to boolean?

  • When using logical operators
  • In a logical context, like in the condition of an if else statement
const money = 0;
if (money) {
  console.log(`Don't spend it all ;)`);
} else {
  console.log(`Get a job!`);
}
Get a job!

So, money is being converted implicitly from a number to a boolean in the logical context above. That happens using the truthy and falsy value rules.

Another use case to check if a variable is defined or not:

let height;
if (height) {
  console.log('Height is defined');
} else {
  console.log('Height is UNDEFINED');
}
Height is UNDEFINED

If we give a value to height instead, it will be considered truthy instead, but since it has no value above, it is falsy.

NOTE: if we give the value of height 0, it will be falsy as well. This is kind of a bug in our app.

We can fix ths using logical operators, but we'll talk about that later.

Equality Operators

By the way, if our if block has only one line, we don't need curly braces {}.

In this example, it only works if age is exactly 18 and no other value. And it returns a boolean value.

const age = 18;
if (age === 18) console.log('You just became an adult');
console.log(18 === 18);
console.log(18 === 19);
You just became an adult
true
false

Besides the triple = (the strict equality operator) we have a double = (the loose equality operator) and that actually does type coercion.

So:

console.log(18 === '18'); // strict
console.log(18 == '18'); // loose
false
true

Avoid the loose equality operator as much as possible to avoid bugs. Default to the strict triple equals operator.

This will prompt you for a value when you load the page:

const favourite = prompt(`What's your favourite number?`);
console.log(typeof favourite); // This will return string

You can wrap the code in the Number function if you want to convert your input:

const favourite = Number(prompt(`What's your favourite number?`));
console.log(typeof favourite); // This will return number now

So far we've only used if else, but we can also use else if.

const favourite = Number(prompt(`What's your favourite number?`));
if (favourite === 42) {
  console.log('42 was a great year!');
} else if (favourite === 18) {
  console.log('18 was a great year too!');
} else {
  console.log('Not a cool year');
}

There is also an operator for 'different'.

!= LOOSE VERSION !== STRICT VERSION

const favourite = 46;
if (favourite !== 23) console.log('Why not 23?');
Why not 23?

Boolean Logic

We're going to learn about the following operators:

  • and &&
  • or ||
  • not !

This is pretty self explanatory so we'll wait for examples.

Just considering the not operator, it inverts true/false value.

Logical Operators

Using the and operator:

const hasDriversLicense = true;
const hasGoodVision = true;

console.log(hasDriversLicense && hasGoodVision);
true

Using the or operator

const hasDriversLicense = false;
const hasGoodVision = false;

console.log(hasDriversLicense || hasGoodVision);
false

Using the not operator

const hasDriversLicense = false;
const hasGoodVision = false;

console.log(!hasDriversLicense);
true

Taking a decision:

const hasDriversLicense = true;
const hasGoodVision = true;
const isTired = false

if (hasDriversLicense && hasGoodVision && !isTired) {
  console.log('Sarah should drive');
} else {
  console.log('Someone else should drive');
}

Sarah should drive

Sarah should drive only if both variables are true and she's not tired.

Coding Challenge #3

const scoreDolphins = (96 + 108 + 89) / 3
const scoreKoalas = (88 + 91 + 110) / 3

if (scoreDolphins > scoreKoalas) {
  console.log('Dolphins win the trophy');
} else if (scoreKoalas > scoreDolphins) {
  console.log('Koalas win the trophy');
} else if (scoreKoalas === scoreDolphins) {
  console.log('Both win the trophy');
}
Dolphins win the trophy

The Switch Statement

This is an alternative way of writing a complicated if / else statement when all we want to do is compare one value to multiple different options.

const day = 'wednesday';

switch(day) {
  case 'monday': // day === 'monday'
    console.log('Plan course structure');
    console.log('Go to coding meetup');
    break;
  case 'tuesday':
    console.log('Prepare theory videos');
    break;
  case 'wednesday':
  case 'thursday':
    console.log('Write code examples');
    break;
  case 'friday':
    console.log('Record videos');
    break;
  case 'saturday':
  case 'sunday':
    console.log('Enjoy the weekend');
    break;
  default:
    console.log('Not a valid day!');
}
Write code examples

Note that we needed to put the break in. If you don't put it in, the code simply continues executing.

Challenge: Let's do the same as an if / else:

const day = 'sunday'

if (day === 'monday') {
  console.log('Plan course structure');
  console.log('Go to coding meetup');
} else if (day === 'tuesday') {
  console.log('Prepare theory videos');
} else if (day === 'wednesday' || day === 'thursday') {
  console.log('Write code examples');
} else if (day === 'friday') {
  console.log('Record videos');
} else if (day === 'saturday' || day === 'sunday') {
  console.log('Enjoy the weekend');
} else if (day !== 'monday' || day !== 'tuesday' || day !== 'wednesday' || day !== 'thursday' || day !== 'friday' || day !== 'saturday' || day !== 'sunday') {
  console.log('Not a valid day!');
}
Enjoy the weekend

Whoo… that was much more work than using switch.

Statements and Expressions

An expression is a piece of code that produces a value like 3 + 4

Or 1991 is an expression too because it produces a value.

or true && false && !false

A statement is like a bigger piece of code which is executed but does not produces a value itself.

Example:

if (23 > 10) {
  const str = '23 is bigger';
}

This is a statement that declares the variable str but it doesn't produce a value.

But the str is an expression because it produces a value.

It's all a bit fuzzy. Expressions produce values, and statements are like full sentences that translate our actions.

Whenever something ends in a semicolon, that's a statement.

So in a template literal, you can only insert expressions and not statements.

The Conditional (Ternary) Operator (?)

Two ways of writing conditions:

  • if / else
  • switch

There's another:

const age = 23;
age >= 18 ? console.log('I can buy cigarettes.') : console.log(`I'm a sad teenager`);
I can buy cigarettes.

So the else statement comes after the colon and it is mandatory.

So this is an if/else statement all in one line using the ? conditional operator or the ternary operator.

Three parts:

  • The condition
  • The if part
  • The else part

An operator always produces a value so it is an expression. If we have a value, we can assign a variable. So more usually, we do it like this:

const age = 23
const drink = age >= 18 ? 'wine' : 'water';
console.log(drink);
wine

To do this with if / else:

const age = 16
let drink2;
if (age >= 18) {
  drink2 = 'wine';
} else {
  drink2 = 'water';
}
console.log(drink2);
water

Quite a bit more clumsy! We need to define outside the drink2 variable outside of the if/else block for scoping purposes.

We can take it further now and use it in a template literal because it is an expression and not a statement:

const age = 18
console.log(`I like to drink ${age >= 18 ? 'wine' : 'water'}`);
I like to drink wine

WOW!!!

When we have bigger blocks of code we need to execute, if / else is still going to be the best option. But if we need to make a quick decision, then the ternary operator is great.

Coding Challenge #4

const bill = 275;
const tip = bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.2;
const finalBill = bill + tip
console.log(`The bill was ${bill}, the tip was ${tip}, and the total value ${finalBill}.`)
The bill was 275, the tip was 41.25, and the total value 316.25.

We could have also just evaluated the finalBill within the template literal as ${bill + tip}.

JavaScript Releases: ES5, ES6+ and ESNext

The best way to understand JS versions is to look at the history of JS.

  • 1995: Netscape hired a guy named Brendan Eich to create the first version of JS (Called Mocha) in 10 days.
  • 1996: Renamed to LiceScript and then renamed to JavaScript (Marketing reasons. The language has nothing to do with Java really. Two completely different languages.
    • MS released Internet Explorer and released JScript… competing language but basically the same.
  • 1997: ECMA releases ES1 and it was standardized.
  • 2009: ES5 is released with a lot of new features.
  • 2015: ES6 (ES2015) is released. Single biggest update to the language.
    • ECMA changed to an annual release cycle.
  • 2016 onware: Release every year.

JS has backwards compatibility all the way to ES1. That means you can run old JS in a new browser without having to rely on version numbers.

The fundamental principle: Don't break the web!!!

New versions do not contain breaking changes. They are always incremental updates. So it's better to call them releases and not versions.

Regarding forwards compatibility, if you run future code in an old browser, it doesn't work. JS is not forwards compatible.

This brings us to our next topic: How can we use modern JS today because browsers that users are using might be old.

Consider 2 distinct scenarios:

Development:

  • Use the most up-to-date version of the Chrome browser

Production:

  • Use Babel to transpile and polyfill your code(converting back to ES5 to ensure browser compatibility for all users). This is necessary only after your app is developed and you want to ship to your users.

ES5 is fully supported in all browsers today. That's why it's the target for transpiling.

ES6+ is will supported in all modern browsers. You can use most features in production with transpiling and polyfilling.

Here's the ES6 compatibility table: http://kangax.github.io/compat-table

ESNext is 2021 onward.

How are versions and releases taught in this course?

  • Jonas will teach modern JS right from the beginning in this course.
  • It's important to learn how things used to be done before ES6. Like const & let vs. var
    • You will better understand how JS works
    • Many tutorials and code you find online today are still in ES5
    • As a developer, you'll probably need to work with old codebases

Section 3: JavaScript Fundamentals - Part 2

Activating Strict Mode

All you have to do is write this at the beginning of the script. It must be the first statement in the script:

'use strict';

You can also activate strict mode for specific function or block, but Jonas doesn't really do that.

Strict mode makes it easier to avoid introducing bugs into the code for two reasons:

  1. Strict mode forbids us to do certain things.
  2. It makes more visible errors and without it, sometimes JS fails silently.

Example:

'use strict'; // with this line commented out, no error is surfaced! JS fails silently
let hasDriversLicense = false;
const passTest = true;

if (passTest) hasDriverLicense = true; // notice we omitted the s and spelled the var name wrong.
if (hasDriversLicense) console.log('I can drive!');
ReferenceError: hasDriverLicense is not defined

Without strict mode, we wouldn't know about the bug above!

Another thing that strict mode does is to introduce a short list of variable names that might be added to the language later. Notice that the variable name interface or private is not allowed in strict mode.

'use strict'
const interface = 'Audio';
SyntaxError: Unexpected strict mode reserved word

Everything in the future in this course will assume strict mode is enabled.

Functions

The fundamental building block of real-world JS applications is functions.

A function is a piece of code that we can re-use over and over again… like a variable, but for whole chunks of code.

Let's declare our first function: Note that within the curly braces {} is referred to as the function body.

// defining the function:
function logger() {
  console.log('My name is Aleks');
}

// calling the functions:
logger();
My name is Aleks

We invoke/run/call the function by just naming it followed by parens () as we did above.

Usually, when we write functions, we also pass data into a function. Functions can also return data to us to use later in the code:

Now, we'll specify parameters (input data) within the parens when we define the function…

function fruitProcessor(apples, oranges) {
  console.log(apples, oranges);
  const juice = `Juice with ${apples} apples and ${oranges} oranges.`;
  return juice;
}

const appleJuice = fruitProcessor(5, 0);
console.log(appleJuice);
5 0
Juice with 5 apples and 0 oranges.

So we called the fruitProcessor function with 2 arguments, 5, and 0. But we need to assign the return value to another variable. So we saved the value into the appleJuice variable and logged that to the console. We could have also just logged the result of function directly to the console with:

console.log(fruitProcessor(5, 0));

Function Declarations vs. Expressions

When we use the function keyword, these are called function declarations.

Here's another example:

//function declaration:

function calcAge1(birthYear) {
  return 2024 - birthYear;
}

const age1 = calcAge1(1981);

// Now let's create a function expression instead of a declaration.
// This makes an anonymous function.

const calcAge2 = function (birthYear) {
  return 2024 - birthYear;
}

const age2 = calcAge2(1981);
console.log(age1, age2);

43 43

Expressions produce values. Functions are just values and therefore they can be stored in variables.

What's the big difference between function declarations and function expressions?

The main practical difference, is we can actually call function declarations before they are defined in the code. This happens because of a process called hoisting. You can't do the same with the expression.

Another question. Which should I use when I write my own functions?

It's often just a matter of personal preference. Jonas prefers function expressions where he has to define all functions first at the top of the code. He also likes everything stored in variables. Many other developers don't agree with this.

Arrow Functions

There's a third type of function that was added in ES6: the Arrow Function.

It's a special form of function expression that is shorter and therefore faster to write.

// function expression:
const calcAge2 = function (birthYear) {
  return 2024 - birthYear;
}

// arrow function:
const calcAge3 = birthYear => 2024 - birthYear;

const age3 = calcAge3(1981);
console.log(age3);
43
  • So we don't need the curly braces
  • The return happens implicitly
  • Excellent for one-liner functions

Let's write a more complex example:

// Here's our function from before:
const calcAge3 = birthYear => 2024 - birthYear;

// Here's our new function:
const yearsUntilRetirement = (birthYear, firstName) => {
  const age = 2024 - birthYear;
  const retirement = 65 - age;
  return `${firstName} retires in ${retirement} years.`;
}

console.log(yearsUntilRetirement(1981, 'Aleks'));
Aleks retires in 22 years.

As the code gets more complex, we kind of lose the advantage of using an arrow function. Arrow functions are good for one-liners.

Arrow functions also do not get a 'this' keyword. Don't know what this means yet.

Functions Calling Other Functions

function cutFruitPieces(fruit) {
  return fruit * 4;
}

function fruitProcessor(apples, oranges) {
  const applePieces = cutFruitPieces(apples);
  const orangePieces = cutFruitPieces(oranges);
  const juice = `Juice with ${applePieces} apple pieces and ${orangePieces} orange pieces.`;
  return juice;
}

console.log(fruitProcessor(2, 3));
Juice with 8 apple pieces and 12 orange pieces.

Question: Why not simply multiply the input values by 4 and call it a day? We did it the way above for:

  • It's common for one function to call another function
  • It's good to illustrate 'Don't repeat yourself' in the case that we have to alter any function.

Reviewing Functions

// We have two functions called birthYear but it's a local variable to each function.
const calcAge = function(birthYear) {
  return 2037 - birthYear;
}

const yearsUntilRetirement = function(birthYear, firstName) {
  const age = calcAge(birthYear);
  const retirement = 65 - age;

  if(retirement > 0) {
    return `${firstName} retires in ${retirement} years.`;
  } else {
    return `${firstName} has already retired`;
  }
}

console.log(yearsUntilRetirement(1970, 'Aleks'));

Aleks has already retired

The function always exist immediately as soon as it hits the return. So any code after return will not be executed.

3 Types of functions:

  • Function declaration: Can be used before it's declared in the code.
  • Function expression: Essentially a function value stored in a variable.
  • Arrow function: Great for quick one-line functions. Has no this keyword.

The parts of a function: fdaa1cfd5ea8419393e474db1b9cf992.png

Coding Exercise 5: Challenge #1

// below I could have just named the vars a, b, c, since could use it for any kind of average.
const calcAverage = (scoreOne, scoreTwo, scoreThree) => (scoreOne + scoreTwo + scoreThree) / 3;

const scoreDolphins = calcAverage(85, 54, 41);
const scoreKoalas = calcAverage(23, 34, 27);

function checkWinner(avgDolphins, avgKoalas) {
  if (avgDolphins >= avgKoalas * 2) {
    console.log(`Dolphins win (${avgDolphins} vs. ${avgKoalas})`);
  } else if (avgKoalas >= avgDolphins * 2) {
    console.log(`Koalas win (${avgKoalas} vs. ${avgDolphins})`);
  } else {
    console.log('No team wins...');
  }
}

checkWinner(scoreDolphins, scoreKoalas);
Dolphins win (60 vs. 28)

Introduction to Arrays

Our first data structure! Let's say I want to store my friends' names in variables:

const friend1 = 'Michael';
const friend2 = 'Steven';
const friend3 - 'Peter';

This isn't efficient. Let's bundle values together into an array:

const friends = ['Michael', 'Steven', 'Peter'];
console.log(friends);
[ 'Michael', 'Steven', 'Peter' ]

Here's another way to create an array with the Array function. We also had to use the new keyword:

const years = new Array(1991, 1984, 2008, 2020);
console.log(years);
[ 1991, 1984, 2008, 2020 ]

To get items out of an array:

const friends = ['Michael', 'Steven', 'Peter'];
console.log(friends[0]);
console.log(friends.length); // length is a property and we get the amount of elements in the array
console.log(friends[friends.length - 1]); // here we got the last item in the array
Michael
3
Peter

Note that arrays are 0 based. So with the notation above, we accessed the first item int he array.

Note that we can also put any expression within the square brackets.

So with the square brackets, we can also add to an array, or remove or sub in an array. Let's mutate the array!

const friends = ['Michael', 'Steven', 'Peter'];
friends[2] = 'Jay';
console.log(friends);
[ 'Michael', 'Steven', 'Jay' ]

Wait, but we declared the friends array with const so how were we able to mutate it? Only primitive values are immutable, but you can always mutate an array. But note that we can't replace the entire array. But you can mutate the array.

Arrays can also hold values with different types, all at the same time. Note that we even put the friends array inside the array below:

const friends = ['Michael', 'Steven', 'Peter'];
const firstName = 'Aleks';
const aleks = [firstName, 'Ozolins', 2024-1981, 'musician', friends]
console.log(aleks);
console.log(aleks.length);
[
  'Aleks',
  'Ozolins',
  43,
  'musician',
  [ 'Michael', 'Steven', 'Peter' ]
]
5

Here's an exercise.

Let's say we have an array of birth years, and we wans to calculate the age for some of them:

const calcAge = function(birthYear) {
  return 2037 - birthYear;
}

const years = [1990, 1967, 2002, 2010, 2018];

// calcAge(years); THIS WONT WORK

const age1 = calcAge(years[0]);
const age2 = calcAge(years[2]);
const age3 = calcAge(years[years.length - 1]);
console.log(age1, age2, age3);

// or we can write the results to an array:

const ages = [calcAge(years[0]), calcAge(years[2]), calcAge(years[years.length - 1])];
console.log(ages)

47 35 19
[ 47, 35, 19 ]

Basic Array Operations (Methods)

There are countless array methods. Here are a few:

const friends = ['Michael', 'Steven', 'Peter'];

friends.push('Ted'); // push adds elements to an array
console.log(friends);

const newLength = friends.push('Helen'); // push also returns a value... the new array length
console.log(newLength);

[ 'Michael', 'Steven', 'Peter', 'Ted' ]
5

There's also the unshift method which will add elements to the beginning of the array:

const friends = ['Michael', 'Steven', 'Peter'];

friends.unshift('Johnny'); // unshift adds an element to the beginning of the array
console.log(friends);
[ 'Johnny', 'Michael', 'Steven', 'Peter' ]

There's also methods to remove elements from arrays.

const friends = ['Michael', 'Steven', 'Peter'];
friends.pop(); // Remove the last elemenet from the array
console.log(friends);

const popped = friends.pop();
console.log(popped); // the pop method returns the element that has been removed.
[ 'Michael', 'Steven' ]
Steven

Notice Peter is now gone!

To remove the first element from the array, just call the shift method without and arguments:

const friends = ['Michael', 'Steven', 'Peter'];
friends.shift();
console.log(friends);
[ 'Steven', 'Peter' ]

Once again, shift will return the element that was removed.

To find out the position of a certain element, use the indexOf method:

const friends = ['Michael', 'Steven', 'Peter'];
console.log(friends.indexOf('Steven'));
1

Finally, there's a similar method that's an ES6 method called includes:

const friends = ['Michael', 'Steven', 'Peter'];
console.log(friends.includes('Steven'));
console.log(friends.includes('Bob'));

// We can use the includes method to write conditionals:

if (friends.includes('Steven')) {
  console.log('Steven is here.');
} else {
  console.log('Steven is not here.');
}
true
false
Steven is here.

Coding Exercise 6: Challenge #2

function calcTip(billValue) {
  let tip
  if (billValue >= 50 && billValue <= 300) {
    tip = billValue * 0.15;
  } else {
    tip = billValue * 0.2;
  }
  return tip;
}

console.log(calcTip(100));

const bills = [125, 555, 44];
console.log(bills);

const tips = [calcTip(bills[0]), calcTip(bills[1]), calcTip(bills[2])];
console.log(tips);

const totals = [bills[0] + tips[0], bills[1] + tips[1], bills[2] + tips[2]];
console.log(totals);
15
[ 125, 555, 44 ]
[ 18.75, 111, 8.8 ]
[ 143.75, 666, 52.8 ]

Note that we could define the billValue function more easily this way using the ternary operator:

const calcTip = function (bill) {
  return bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.2;    
}

Or using an arrow function as a one-liner.

Introduction to Objects

Oh by the way, you can write arrays as objects:

const aleksArray = [
  'Aleks',
  'Ozolins',
  1981
];

In arrays, there are no ways to give elements name. We only reference their position in the array. To solve that problem, we have objects where we define key/value pairs.

This is the object literal syntax

const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 2024 - 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul']
};

So, the variable names are keys, and the values are… well… values. The keys are also called properties.

In objects, the order of the objects does not matter at all. In arrays, it does, because that's how we access those elements.

  • We should use arrays for ordered data
  • We should use objects for unstructured data

How do we get data from an object?

Dot vs. Bracket Notation

  • How to retrieve data from objects
  • Hot to change data
const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 2024 - 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul']
};

console.log(aleks);
console.log(aleks.lastName); // Using the dot notation to retrieve a property
console.log(aleks['lastName']); // Using the bracket notation

const nameKey = 'Name';
console.log(aleks['first' + nameKey]); // We can put any expression in the brackets

{
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 43,
  job: 'musician',
  friends: [ 'Ted', 'Jeff', 'Paul' ]
}
Ozolins
Ozolins
Aleks

Note that in the bracket notation above, we need to use a string – we can use any expression.

In what situations should we use dot notation and when should we use bracket notation?

  • When we need to compute the property name, we should use the bracket notation.
  • In other cases, use the dot notation because it is cleaner.

Let's say we don't know what property we will need:

const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 2024 - 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul']
};

const interestedIn = prompt('What do you want to know about Aleks? Type firstName, lastName, age, job, or friends.')

// console.log(aleks.interestedIn); // This will give us indefined.
// So we need to do it this way:
console.log(aleks[interestedIn]);

So in the case above, we needed to use the bracket notation because the expression within the brackets will get evaluated.

Let's print some custom string when the user tries to access a property that does not exist:

if(aleks[interestedIn]) { // This is evaluating whether interestedIn is truthy (exists)
  alert(aleks[interestedIn]);
} else {
  alert('Not a property!');
}

Let's learn how to use the dot and bracket notation to add properties to an object.

const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 2024 - 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul']
};

aleks.location = 'NJ'; // adding with dot notation
aleks['website'] = 'https://www.ozolins.xyz'; // adding with bracket notation.
console.log(aleks);
{
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 43,
  job: 'musician',
  friends: [ 'Ted', 'Jeff', 'Paul' ],
  location: 'NJ',
  website: 'https://www.ozolins.xyz'
}

Small challenge:

Write a sentence in a dynamic way like this: 'Aleks has 3 friends and his best friend is called Ted.' Don't hard code the values but program the bold values.

const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  age: 2024 - 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul']
};

console.log(`${aleks.firstName} has ${aleks.friends.length} friends and his best friend's name is ${aleks.friends[0]}.`);
Aleks has 3 friends and his best friend's name is Ted.

Note that length is a property that is available on all arrays even though we don't define it ourselves!

The operator precedence above is left to right. That's why aleks.friends.length works.

Object Methods

Objects, just like arrays, can hold different types of data.

Remember that functions are just values. That means that we can create a key/value pair in which the value is a function:

const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  birthYear: 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul'],
  hasDriversLicense: true,

  calcAge: function() {
    return 2024 - this.birthYear;  // this points to aleks so this.birthYear points to 1981
  },

  // Let's say we need to access the age multiple times in our program. We could instead say:

  calcAge2: function() {
    this.age2 = 2024 - this.birthYear;
    return this.age2;
  }
};

console.log(aleks.calcAge()); // using dot notation
console.log(aleks['calcAge']()); // using bracket notation

console.log(aleks.calcAge2());
console.log(aleks.age2); // this is more efficient.


43
43
43
43

Any function that is attached to an object is called a method. Notice above that we needed to use a function expression and not a declaration.

Notice above we used the this keyword. The this keyword is equal to the object calling the method.

Challenge: Write a method called getSummary and this method shold return a string that should summarize the data about the person (Aleks or otherwise).

Write this: Aleks is a 43 year old teacher, and he has a driver's license.

const aleks = {
  firstName: 'Aleks',
  lastName: 'Ozolins',
  birthYear: 1981,
  job: 'musician',
  friends: ['Ted', 'Jeff', 'Paul'],
  hasDriversLicense: true,
  calcAge: function() {
    this.age = 2024 - this.birthYear;
    return this.age;
  },
  getSummary: function() {
    return this.summary = `${this.firstName} is a ${this.calcAge()} year old ${this.job} and ${(this.hasDriversLicense) ? `he has a driver's licence.` : `he does not have a driver's licence.`}`;
  }
}

console.log(aleks.getSummary()); // We have to call the function before the property is stored in the object.
console.log(aleks.summary); // Now this is from the object.

Aleks is a 43 year old musician and he has a driver's licence.
Aleks is a 43 year old musician and he has a driver's licence.

Coding Exercise 7: Challenge #3

const mark = {
  fullName: 'Mark Miller',
  mass: 78,
  height: 1.69,
  calcBMI: function() {
    this.bmi = this.mass / (this.height * this.height);
    return this.bmi;
  }
}

const john = {
  fullName: 'John Smith',
  mass: 92,
  height: 1.95,
  calcBMI: function() {
    this.bmi = this.mass / (this.height * this.height);
    return this.bmi;
  }
}

mark.calcBMI();
john.calcBMI();
console.log(mark);

if (john.bmi > mark.bmi) {
  console.log(`${john.fullName}'s BMI (${john.bmi}) is higher than ${mark.fullName}'s (${mark.bmi})!`);
} else {
  console.log(`${mark.fullName}'s BMI (${mark.bmi}) is higher than ${john.fullName}'s (${john.bmi})!`);
}
{
  fullName: 'Mark Miller',
  mass: 78,
  height: 1.69,
  calcBMI: [Function: calcBMI],
  bmi: 27.309968138370508
}
Mark Miller's BMI (27.309968138370508) is higher than John Smith's (24.194608809993426)!

Iteration: The for Loop

The if else statement is a control structure. One of the other control structures is loop.

Loops are fundamental to every programming language because they allow us to automate.

This is not efficient:

console.log('Lifting weights repetition 1');
console.log('Lifting weights repetition 2');
console.log('Lifting weights repetition 3');

// It's not efficient
Lifting weights repetition 1
Lifting weights repetition 2
Lifting weights repetition 3

Instead we'll create a for loop:

Loop statement has 3 parts:

  • The initial value of the counter let rep = 1 – Note we need to use let
  • A logical condition that is evaluated before each iteration of the loop rep <= 10
    • In each iteration fo the loop, the rep counter will increase by 1
    • The loop will keep running while the condition is true
  • How we increase the value of the counter rep++ which is the same as rep = rep + 1
for (let rep = 1; rep <= 10; rep++) {
  console.log(`Lifting weights repetition ${rep}`);
}
Lifting weights repetition 1
Lifting weights repetition 2
Lifting weights repetition 3
Lifting weights repetition 4
Lifting weights repetition 5
Lifting weights repetition 6
Lifting weights repetition 7
Lifting weights repetition 8
Lifting weights repetition 9
Lifting weights repetition 10

Looping Arrays, Breaking and Continuing

We will need to loop through arrays! Let's say we want to log every element to the console.

  • That a traditional counter varibale name is i. So, we'll use that here.
  • We are starting with position 0 below since we're dealing with an array.
  • We are using aleks.length to decide how many iterations to loop through.
const aleks = [
  'Aleks',
  'Ozolins',
  2024 - 1981,
  'musician',
  ['Ted', 'Jeff', 'Paul']
];

for (let i = 0; i < aleks.length; i++) {
  console.log(aleks[i] + ": Type - " + typeof aleks[i]);
}
Aleks: Type - string
Ozolins: Type - string
43: Type - number
musician: Type - string
Ted,Jeff,Paul: Type - object

Let's now create a new arraw which will create all the types for these elements:

 const aleks = [
   'Aleks',
   'Ozolins',
   2024 - 1981,
   'musician',
   ['Ted', 'Jeff', 'Paul'],
   true
 ];

const types = []; // This creates an empty array.

for (let i = 0; i < aleks.length; i++) { // Reading from the Jonas array
  // types[i] = typeof aleks[i]; // Filling the types array
  types.push(typeof aleks[i]); // This also fills the array
}

console.log(types);
[ 'string', 'string', 'number', 'string', 'object', 'boolean' ]

Here's another practical example where we will calculate the age for all of the birthyears and return it to a new array.

const years = [1991, 2007, 1969, 2020];
const ages = []

for (let i = 0; i < years.length; i++) {
  ages.push(2024 - years[i]);
}

console.log(ages);
[ 33, 17, 55, 4 ]

Let's learn about 2 important statements for loops:

  • continue: Exit the current iteration of the loop and continue to the next one.
  • break: Completely terminate the whole loop.

Let's start with continue:

const aleks = [
  'Aleks',
  'Ozolins',
  2024 - 1981,
  'musician',
  ['Ted', 'Jeff', 'Paul'],
  true
];

console.log('---ONLY STRINGS---');
for (let i = 0; i < aleks.length; i++) {
  if (typeof aleks[i] !== 'string') continue; // Only log strings to the console. Else, restart the loop.
  console.log(aleks[i]);
}

---ONLY STRINGS---
Aleks
Ozolins
musician

How about the break statement:

const aleks = [
  'Aleks',
  'Ozolins',
  2024 - 1981,
  'musician',
  ['Ted', 'Jeff', 'Paul'],
  true
];

console.log('--BREAK AT NUMBER---');
for (let i = 0; i < aleks.length; i++) {
  if (typeof aleks[i] === 'number') break; // Only log strings to the console. Else, restart the loop.
  console.log(aleks[i]);
}
--BREAK AT NUMBER---
Aleks
Ozolins

Looping Backwards and Loops in Loops

  • We will loop over an array backwards
  • We will create a loop in an loop

First, backwards:

const aleks = [
  'Aleks',
  'Ozolins',
  2024 - 1981,
  'musician',
  ['Ted', 'Jeff', 'Paul'],
  true
];

for (let i = aleks.length -1; i >= 0; i--) {
  console.log(aleks[i]);
}
true
[ 'Ted', 'Jeff', 'Paul' ]
musician
43
Ozolins
Aleks

Now, a loop in a loop. Let's go back to the gym example, but let's say we have 3 exersises, and we want to repeat each one 3 times.

for (let ex = 1; ex <= 3; ex++) { // ex <= 3 is same as writing ex < 4
  console.log(`--Starting Exercise ${ex}--`);

  for (let rep = 1; rep <=3; rep++) {
    console.log(`Exercise ${ex} Rep ${rep}`);
  }
} 
--Starting Exercise 1--
Exercise 1 Rep 1
Exercise 1 Rep 2
Exercise 1 Rep 3
--Starting Exercise 2--
Exercise 2 Rep 1
Exercise 2 Rep 2
Exercise 2 Rep 3
--Starting Exercise 3--
Exercise 3 Rep 1
Exercise 3 Rep 2
Exercise 3 Rep 3

The While Loop

  • In a while loop, we can only specify a condition.
  • We declare the counter outside of the loop before.
  • The while loop is more versatile because:
    • It does not really need a counter. It only needs a condition (any condition unrelated to a counter).
// Here's using the for loop:
console.log('---FOR LOOP---');
for (let rep = 1; rep <= 5; rep++) {
  console.log(`Lifting weights repetition ${rep}`);
}

// Here's the while loop:
console.log('---WHILE LOOP---');
let rep = 1;
while (rep <= 5) { // The loop will run while the condition is true
  console.log(`Lifting weights repitition ${rep}`);
  rep++;
}  

---FOR LOOP---
Lifting weights repetition 1
Lifting weights repetition 2
Lifting weights repetition 3
Lifting weights repetition 4
Lifting weights repetition 5
---WHILE LOOP---
Lifting weights repitition 1
Lifting weights repitition 2
Lifting weights repitition 3
Lifting weights repitition 4
Lifting weights repitition 5

Example of a while loop without a counter:

  • We will roll a dice until we roll a 6 and then we stop.
  • We don't know how many times the loop will run.
let dice = Math.trunc(Math.random() * 6) + 1; // Creates a number between - and 1 and 6

while (dice !==6) {
  console.log(`You rolled a ${dice}`);
  dice = Math.trunc(Math.random() * 6) + 1;
  if (dice === 6) console.log(`We're done: you rolled a 6!`);
}
You rolled a 5
You rolled a 1
You rolled a 4
You rolled a 1
You rolled a 1
We're done: you rolled a 6!

So the while loop really doesn't depend on a counter variable.

  • Use for when you need a counter variable.
  • Use while when you don't need a counter variable.

Coding Exercise 8: Challenge #4

const calcTip = function (bill) {
  return bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.2;
}

/* Write your code below. Good luck! 🙂 */

const bills = [22, 295, 176, 440, 37, 105, 10, 1100, 86, 52];
const tips = [];
const totals = [];

for (let i = 0; i < bills.length; i++) {
  tips.push(calcTip(bills[i]));
  totals.push(tips[i] + bills[i]);
  console.log(`-------\n\Bill: ${bills[i]}\n\Tip: ${tips[i]}\n\Total: ${totals[i]}`);
}

// Bonus: Write a function calcAverage which takes an array called arr as an argument. This function calculates the average of all numbers in the given array.

const calcAverage = function (arr) {
  let sum = 0
  for (let i = 0; i < arr.length; i++) {
    // sum = sum + arr[i];
    sum += arr[i]; // this is more efficient than the line above
  }
  return sum / arr.length
}

console.log(`-------\n\Average of bill totals: ${calcAverage(totals)}`);
-------
Bill: 22
Tip: 4.4
Total: 26.4
-------
Bill: 295
Tip: 44.25
Total: 339.25
-------
Bill: 176
Tip: 26.4
Total: 202.4
-------
Bill: 440
Tip: 88
Total: 528
-------
Bill: 37
Tip: 7.4
Total: 44.4
-------
Bill: 105
Tip: 15.75
Total: 120.75
-------
Bill: 10
Tip: 2
Total: 12
-------
Bill: 1100
Tip: 220
Total: 1320
-------
Bill: 86
Tip: 12.9
Total: 98.9
-------
Bill: 52
Tip: 7.8
Total: 59.8
-------
Average of bill totals: 275.19

Section 4: How to Navigate This Course

Pathways and Section Roadmaps

  • We're going to plan our unique journey through the course.
  • There are some sections you can skip if you want.
  • There are roadmaps at the beginning of each section and they say which videos are:
    • Very important
    • Good to know
    • Optional

Here are some pathways for the subsequent sections: 32c380ac00de11e1517e1327854d24ce.png

I think I'm just going to watch everything but skip videos as needed if they don't appear important.

Section 5: Developer Skills and Editor Setup

*SKIPPING THIS SECTION FOR NOW SINCE I'M NOT USING VS CODE

Section 6: [OPTIONAL] HTML & CSS Crash Course

Basic HTML Structure and Elements

  • Every HTML document has an html tag
    • What is visible on the page
  • And a head and body tag
    • head is like describing the page.
    • Favicons go in head
<! DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0" />
    <title>Learning HTML & CSS</title>
  </head>
  <body>
    <h1>JavaScript is fun, but so is HTML & CSS!</h1>
    <p>
      You can learn JavaScript without HTML and CSS, but for DOM manipulation it's useful tohave some basic ideas of HTML & CSS.
    </p>
    <h2>Another heading</h2>
    <p>
      Just another paragraph
    </p>
  </body>
</html>
  • <p> Paragraph tag
  • <h1> Heading tag

I set up Alfred so I can type `html to fill in the basic HTML structure below. I should probably move this to yasnippet later.

<! DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
  </body>
</html>

Attributes, Classes and IDs

Attributes describe elements.

<! DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0" />
    <title>Learning HTML & CSS</title>
  </head>
  <body>
    <h1>JavaScript is fun, but so is HTML & CSS!</h1>
    <p class="first">
      You can learn JavaScript without HTML and CSS, but for DOM manipulation it's useful tohave some basic ideas of HTML & CSS. You can visit <a href="https://ozolins.xyz">Aleks' Webpage</a>.    
    </p>

    <img id="aleks-image" src="https://ozolins.xyz/images/headshot.jpg" />
    <h2>Another heading</h2>
    <p calss="second">
      Just another paragraph.
    </p>
  </body>
</html>

So above we've inserted an <a> anchor tag and it has an href attribute. We're describing the <a> element.

The <a> element is an inline element because it's inline with the rest of the text.

The <h2> element is a block element.

The <img> element above also has attributes, one of which is the src attribute.

Note that the <img> Tag does not have a closing tag so we close it right at the end of the first tag. This is optional.

2 Very important attributes that we can use on all elements:

  • Classes
  • IDs

We use these to name elements so that we can select them in CSS and style them. We also use IDs and classes to select elements in JS when we do DOM manipulation.

Note that we assigned classes to the first and second paragraphs above, and we added an id to the image.

We almost never use ids to style elements or select them in JS.

Date: 2024-03-14 Thu 07:11

Emacs 29.4 (Org mode 9.6.15)