## JavaScript First Steps ### A [FrontendMasters](https://frontendmasters.com) course by [AnjanaVakil](https://twitter.com/AnjanaVakil) [anjana.dev/javascript-first-steps](https://anjana.dev/javascript-first-steps)
# Part 2 -- ### Goals - Write JS in an HTML file - Use functions to perform actions - Handle events to react to user behavior - Use conditionals to decide what to do when - Use loops to repeat actions multiple times - Make our own quiz game! -- ### Ready? # Let's go!
## Pop Quiz! Let's put our knowledge so far to the test! [JS Quiz](./2-jsquiz-fancy.html)
## Writing JS in HTML -- *Where* do we write JS? - The browser's JS `console` - **Local text file in editor, e.g. TextEdit, [VS Code](https://code.visualstudio.com/)** - Online playground e.g. [CodePen](https://codepen.io), [CodeSandbox](https://codesandbox.io) -- ### Let's do it! - Go to [2-jsquiz-starter.html](./2-jsquiz-starter.html) - Save the HTML file (Right click > "Save file as...") - Open it in your text editor of choice -- ### Where in the HTML doc does our JS live? -- ### `script` element MDN: [HTML > script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) -- What is all this about? ```js // TODO some instructions here ``` -- ### comments Start with `//` Help others (and yourself) understand your code Help keep track of things you want to do -- We'll gradually work through these TODOs to make our own quiz! -- ### Exercise Follow the first 3 `TODO` comments to review skills we've covered so far: - declare `statement`, `optionButtons`, and `explanation` variables with their corresponding element(s) - create a `facts` object representing one true/false fact you've learned about JS - use the `statement` element to display your fact
## Functions
-- values *are* things variables *point to* things functions *do* things -- declaring (creating) a function: ```js function half(x) { return x / 2; } ``` calling (using) a function: ```js const one = half(2); ``` -- ### Parameters & Arguments Some functions need more than one value to work ```js function add(x, y) { return x + y; } add(2,3); ``` -- Some functions don't even need any values ```js function getRandomNumber() { return Math.random(); } getRandomNumber(); ``` -- *parameters* are the inputs a function expects ```js function add3(x, y, z) { console.log("My parameters are named x, y, z"); console.log("I received the arguments", x, y, z); return x + y + z; } const sum = add3(4,5,6); ``` *arguments* are the actual values the function is called with -- Parameters should be named like variables, and behave like variables within the function body ```js function doesThisWork("literally a value") { return true; } ``` ```js function howAboutThis(1weirdVariable!) { return true; } ``` -- What happens if we don't call a function with the intended argument(s)? ```js add3(1,2) ``` ```js getRandomNumber("unexpected") ``` -- JS is pretty "loosey-goosey" about missing/extra arguments
What happens depends on your particular code -- ### Return values A `return` statement specifies the function's output value ```js function square(x) { return x * x; } const nine = square(3); ``` -- Some functions don't `return` anything ```js function sayHello(name) { console.log("Oh hi, " + name + "!"); } ``` ```js sayHello("Marc"); ```
-- What value is returned when there's no `return`? ```js const hm = sayHello("Marc"); ```
undefined
-- ### Exercise In the console, declare the following functions: - `multiply`: given 2 numbers, return their product - `yell`: given a lowercase string, log it in all caps to the console - `longerThan`: given 2 arrays, return whether the first is longer than the second -- ## Arrow functions
-- The `=>` "fat arrow" lets us create an unnamed function without much code ```js (x, y) => x + y ``` aka an *arrow function* -- Since arrow functions are expressions, we can assign them to a variable ```js const add = (x, y) => x + y; ``` is equivalent to ```js function add(x, y) { return x + y; } ``` -- Arrow functions are great when we just want to return a value ```js function square(x) { return x*x; } ``` vs. ```js const square = (x) => x*x; ``` -- For one-parameter functions, parentheses are optional ```js x => x*x ``` ```js (x) => x*x ``` -- For multiple parameters, parentheses are required ```js (firstName, lastName) => firstName + " " + lastName ``` -- If we need to do more than just return a value, we can use curly braces for a "normal" function body In that case, we still need a `return` ```js const addAndLog = (x, y) => { let sum = x + y; console.log('The sum is', sum); return sum; } ``` -- ### Exercise In the console, declare the following functions *using arrow functions*: - `divide`: given 2 numbers, return the first divided by the second - `whisper`: given an uppercase string, log it in all lowercase to the console - `shorterThan`: given 2 arrays, return whether the first is shorter than the second -- ### Exercise In the JSQuiz starter, follow TODOs 4 & 5 to - declare functions to disable or enable a button - declare `isCorrect(guess)` function that compares a guess string to your fact's answer string
## Scope
-- In JS it doesn't just matter *what* variables we declare It also matters *where* we declare them *Scope* determines where variables are "in play" -- ```js function declareBankruptcy() { let bankruptcy = true; } declareBankruptcy(); console.log(bankruptcy); ``` -- Scopes are *nested* within the program The widest scope is the **global** scope Each function gets its own new scope within the scope where it was declared -- ```js let planet = "Jupiter"; function scopeOut() { let planet = "Mars"; console.log("Inner planet:", planet); } scopeOut(); console.log("Outer planet:", planet); ``` -- Within each scope, you can access variables declared in a *wider* scope (e.g. global scope) But not those declared in a *narrower* scope (e.g. function scope) -- ```js let globalVariable = "I live in global scope"; function narrowerScope() { console.log(globalVariable); let localVariable = "I live in the function scope"; } narrowerScope(); console.log(localVariable); ``` -- Variables declared with `let` can be modified from within a narrower scope This can be useful, but also dangerous! -- ```js let feeling = "free"; function trap() { feeling = "boxedIn"; } trap(); console.log(feeling); ```
## Events & Handlers Let's make our web page *interactive*! -- Our page right now...
-- The web browser fires *events* when certain things happen on the page For example, when the user clicks somewhere on the page, a `click` event is fired --
-- We can detect events with JS using an *event listener* The `.addEventListener()` method lets us listen for events on a DOM element ```js document.addEventListener("click", () => { console.log("clicked") }); ``` -- `.addEventListener()` takes 2 parameters: - The name of the event to listen to (e.g. `"click"`) - A *handler* function that JS calls when that event is fired on this element --
-- We can do basically whatever we want in the handler function
See the Pen
Exciting
by Anjana Sofia Vakil (
@vakila
) on
CodePen
.
-- JS passes an `event` object to the handler function with information about the event If we accept this as a parameter, we can use it to get details ```js document.addEventListener("click", (event) => { console.log(event); }); ``` -- `event.target` is the element the event fired on (in this case, which element was clicked) ```js document.addEventListener("click", (event) => { console.log(event.target); }); ``` -- ["click"](https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event) isn't the only type of event we can handle - ["dblclick"](https://developer.mozilla.org/en-US/docs/Web/API/Element/dblclick_event) - ["mouseover"](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseover_event) - ["mouseout"](https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseout_event) ...and *lots* [more](https://developer.mozilla.org/en-US/docs/Web/Events)! -- ### Exercise In the console, on our quiz add event listeners to the buttons so that: - When the "true" button is clicked, the button's text becomes "clicked true" - When the "false" button is clicked, the "explanation" div text becomes "clicked false" --
## Loops
-- *Loops* let us run the same chunk of code multiple times ```js for (let rep = 0; rep < 10; rep += 1) { console.log("now doing rep", rep); } console.log("do you even lift bro"); ``` this is called *iteration* -- `for` loops require us to: - declare & initialize a loop counter - give a condition for the loop to keep running - describe how to change (usually increment) the counter each time ```js for (let count = 0; count <= 100; count += 10) { console.log(count); } ``` --
-- `for ... of` loops let us more easily iterate over items in a collection ```js const numbers = [1,2,3]; for (let i = 0; i < numbers.length; i++) { console.log(numbers[i]); } for (let n of numbers) { console.log(n); } ``` -- We can use `for...of` to iterate over characters in a string ```js for (let char of "ALOHA") { console.log(char); } ``` or items in an array ```js for (let item of ["pop", 6, "squish"]) { console.log(typeof item); } ``` because strings & arrays are "iterables" -- ### Exercise In our quiz, follow TODOs 6 & 7 to - Use a `for...of` loop to attach an event listener to each button - Within the event handler, - populate the `explanation` text in the given element - Use another `for...of` loop to disable all the buttons -- ### `map` & `filter` The `map` & `filter` methods also let us process all the items in an array
-- `map` calls a function on each item in an array to create a new array ```js const spices = [ {name: "Emma", nickname: "Baby"}, {name: "Geri", nickname: "Ginger"}, {name: "Mel B", nickname: "Scary"}, {name: "Mel C", nickname: "Sporty"}, {name: "Victoria", nickname: "Posh"} ]; const nicknames = spices.map(s => s.nickname + " Spice"); ``` Arrow functions are useful for this! -- String templates are useful too! Make them with backticks and `${}`, e.g.
`string to insert ${variable} into`
```js s => `${s.nickname} Spice`; ``` is equivalent to ```js s => s.nickname + " Spice" ``` -- `filter` calls a true/false function on each item and creates a new array with only the items where the function returns true ```js const mels = spices.filter(s => s.name.includes("Mel")); ``` -- ### Exercise From the `spices` array, use `map` and `filter` to: - create a new array `names` with only the name of each girl - create a new array `endInY` with just the girls whose nickname ends in "y" -- ### Spread (`...`) Is another neat trick for iterating over arrays
It lets us take all the items in an array and spread 'em around -- We can use it to put all the items from one array inside another array ```js const oldBurns = ["square", "wack"]; const newBurns = ["basic", "dusty", "sus"]; const burnBook = [...oldBurns, ...newBurns]; ``` equivalent to ```js const burnBook = oldBurns.concat(newBurns); ``` -- We can also use it to pass all the items from an array as arguments to a function or method ```js const skills = ["HTML", "CSS", "JS"]; const newSkills = ["React", "TypeScript", "Node"] skills.push(...newSkills); console.log(...skills); ```
## Conditionals
-- `if` statements let us execute code under a certain *condition* ```js const you = {wannaBeMyLover: true}; if (you.wannaBeMyLover) { you.gottaGetWithMyFriends = true; } ``` code in the `if` block only runs if the `(condition)` is true -- we can use `else` to run other code if `(condition)` is false ```js if (you.reallyBugMe) { console.log("Goodbye"); } else { console.log("Hello"); } ``` -- What will happen when this code runs? ```js if (5 > 4) { console.log("greater than"); } else { console.log("less than"); } ``` -- We can chain `else` and `if` blocks to account for multiple conditions ```js function compare(x, y) { if (x > y) { console.log(x, "is greater than", y); } else if (x < y) { console.log(x, "is less than", y); } else { console.log(x, "is equal to", y); } } ``` -- The `(condition)` is usually an expression that evaluates to a boolean ```js if (forecast === "rain") { console.log("bring an umbrella"); } ``` -- If it's given some other value, JS will convert it to a boolean and decide based on its "truthiness" ```js if ("nonempty strings are truthy") { console.log("this line will run"); } ``` -- ```js if (0) { console.log("zero is truthy"); } else { console.log("zero is falsy"); } ``` -- ### Exercise - Write a conditional that logs a message saying whether your first name or last name is longer - Write a function `isEmpty(array)` that returns whether a given array is empty or not - Is an empty array truthy or falsy? Write a conditional to find out -- ### Boolean (logical) operators Sometimes we care about the opposite of a value ```js let someoneIsAroundYou = false; if (!someoneIsAroundYou) { console.log("baby I love you"); } ``` The `!` operator negates a boolean (gives its opposite) -- Sometimes we care about the truthiness of more than one value ```js if (you.happy && you.knowIt) { you.clapHands(); } ``` -- *Logical operators* let us make two boolean values become one
-- Logical "and" (`&&`) requires both values to be truthy `A` | `B` | `A && B` -- | -- | -- `true` | `true` | `true` `true` | `false` | `false` `false` | `true` | `false` `false` | `false` | `false` -- Logical "or" (`||`) requires only one value to be truthy `A` | `B` | `A \|\| B` -- | -- | -- `true` | `true` | `true` `true` | `false` | `true` `false` | `true` | `true` `false` | `false` | `false` -- ### Conditional ternary operator JS also has a "shortcut" operator for writing quick conditionals it needs 3 values to work: ```js condition ? valueIfTrue : valueIfFalse; ``` -- ```js let mood = forecast === "sunny" ? "happy" : "sad"; ``` is equivalent to ```js let mood; if (forecast === "sunny") { mood = "happy"; } else { mood = "sad"; } ``` -- ### Exercise In our Quiz, follow TODO 8 to complete the event handler function: - Get the guessed value, i.e. value of whichever button was clicked - Compare the guessed value to the real answer using your `isCorrect` function - Use a conditional to add the "correct" or "incorrect" class to the clicked button `element.classList.add("classname")` lets you add a CSS class
## Great job!!