The Complete JavaScript Course 2024 Notes
Table of Contents
- Section 1: Welcome, Welcome, Welcome
- Section 2: JavaScript Fundamentals - Part 1
- Setting Up Our Code Editor
- Hello World and The Console
- A Brief Introduction to JavaScript
- Linking a JS File
- Values and Variables
- Data Types
- let, const, and var
- Basic Operators
- Operator Precedence
- Coding Challenge #1
- Strings and Template Literals
- Taking Decisions: if / else Statements
- Coding Challenge #2
- Type Conversion and Coercion
- Truthy and Falsy Values
- Equality Operators
- Boolean Logic
- Logical Operators
- Coding Challenge #3
- The Switch Statement
- Statements and Expressions
- The Conditional (Ternary) Operator (?)
- Coding Challenge #4
- JavaScript Releases: ES5, ES6+ and ESNext
- Section 3: JavaScript Fundamentals - Part 2
- Activating Strict Mode
- Functions
- Function Declarations vs. Expressions
- Arrow Functions
- Functions Calling Other Functions
- Reviewing Functions
- Coding Exercise 5: Challenge #1
- Introduction to Arrays
- Basic Array Operations (Methods)
- Coding Exercise 6: Challenge #2
- Introduction to Objects
- Dot vs. Bracket Notation
- Object Methods
- Coding Exercise 7: Challenge #3
- Iteration: The for Loop
- Looping Arrays, Breaking and Continuing
- Looping Backwards and Loops in Loops
- The While Loop
- Coding Exercise 8: Challenge #4
- Section 4: How to Navigate This Course
- Section 5: Developer Skills and Editor Setup
- Section 6: [OPTIONAL] HTML & CSS Crash Course
These notes are were taken and compiled by Aleks Ozolins.
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:
- HTML
- Responsible for the content of the page
- Represents the noun
<p
- CSS
- Responsible for the presentation of that content
- Represents the adjective
p {color: red}
- 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
orfunction
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
ormyCurrentJob
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 as23.0
- Strings: A sequence of characters used for text like
'Jonas'
- Boolean: can only be
true
orfalse
- 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:
- Strict mode forbids us to do certain things.
- 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:
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 uselet
- 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 asrep = 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:
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
andbody
taghead
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.