Garrick Aden-Buie
rstudio::conf(2020, "JavaScript for Shiny Users")
Why Javascript | http://bit.ly/jsm_19
Why Javascript | http://bit.ly/jsm_19
Why Javascript | http://bit.ly/jsm_19
๐จ๐ผโ๐ป
repl_js()
what is scrabble?
tiles with letters, letters have points, squares have point multipliers
let myScore = 12let yourScore = 33if (true) { console.log('Yay!')}
<
>
repl_example("truthy-falsy")
Try a few of the options below to see which values are truthy and which are falsy.
true
, false
A number, e.g. 42
or 0
A number in a string, e.g. "42"
or "0"
Strings, e.g 'yes'
or 'false'
A negative number
An object and a empty object
An array and an empty array
01:30
false
0
""
null
undefined
NaN
false
0
""
null
undefined
NaN
Everything else.
42 == '42'
true
42 == '42'
true
42 === '42'
false
42 == '42'
true
โ loose equality
42 === '42'
false
โ strict equality
42 != '42'
false
42 !== '42'
true
let myScore = 12let yourScore = 33if (myScore > yourScore) { console.log('Yay!')} else { console.log('bummer')}
'You ' + result + '!'
1 + '1'
?const result = myScore > yourScore ? 'win' : 'lose'console.log(`You ${result}!`)
condition ? true : false
condition ? ๐ : ๐
condition ? ๐ : ๐
Is condition? then ๐ else ๐
repl_example("if-else-game-over")
Use if ... else
or the ternary if
statement to determine the outcome of the game.
Tell the player how they did.
Report the final scores and the final outcome.
Use string addition
points + ' points'`
or template strings
`${points} points`
let scores = {player: 12, opponent: 33}// What's the outcome of the game for player?if (scores.player > scores.opponent) { result = 'won'} else if (scores.player < scores.opponent) { result = 'lost'} else { result = 'tied'}// Tell the player how they didlet outcome = 'You scored: ' + scores.playeroutcome = outcome + '\nOpponent: ' + scores.opponentoutcome = outcome + '\n\nYou ' + resultconsole.log(outcome)
result
: let result = 'tied'
+=
for outcome
We've used variables to structure an object
let player = 12let opponent = 33let scores = {player: 12, opponent: 33}
scores
{"player":12,"opponent":33}
...is sort of the opposite.
We can destructure objects by matching variable names to key names
...is sort of the opposite.
We can destructure objects by matching variable names to key names
scores
{"player":12,"opponent":33}
...is sort of the opposite.
We can destructure objects by matching variable names to key names
scores
let {player, opponent} = scoresconsole.log("player: ", player)console.log("opponent: ", opponent)
player: 12
opponent: 33
const scores = {player: 12, opponent: 33}// rewrite using destructuringif (scores.player > scores.opponent) { result = 'won'} else if (scores.player < scores.opponent) { result = 'lost'} else { result = 'tied'}// Tell the player how they didlet outcome = 'You scored: ' + scores.playeroutcome = outcome + '\nOpponent: ' + scores.opponentoutcome = outcome + '\n\nYou ' + resultconsole.log(outcome)
const wordPoints = [10, 3, 7, 4]
let [first, second] = wordPointsconsole.log({ first, second })
{"first":10,"second":3}
const wordPoints = [10, 3, 7, 4]
let [first, second, ...others] = wordPointsconsole.log({ first, second, others })
{"first":10,"second":3,"others":[7,4]}
...rest gets the rest of the things that weren't pulled out
let [first, second, ...others] = wordPointsconsole.log({ first, second, others })
{"first":10,"second":3,"others":[7,4]}
...rest also works for objects
scores.result = 'You lost'console.log(scores)let {result, ...score} = scoresconsole.log('result: ', result)console.log(score.player)
{"player":12,"opponent":33,"result":"You lost"}
result: You lost
12
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
What will we get if we put them together like this?
let ourPoints = [myPoints, yourPoints]ourPoints
[[3,2,5,4],[7,4,2,8]]
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
If we want a flat array, we can use ...spread
let ourPoints = [...myPoints, ...yourPoints]ourPoints
[3,2,5,4,7,4,2,8]
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
Which is also useful when building up an array
let newPoints = 9myPoints = //________mypoints
๐ค Where do I put the dots?
...myPoints
...myPoints, ...newPoints
...newPoints
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
Which is also useful when building up an array
let newPoints = 9myPoints = [...myPoints, newPoints]myPoints
[3,2,5,4,9]
๐ค Where do I put the dots?
...myPoints
...myPoints, ...newPoints
...newPoints
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// whats our word score?
score = 0
+=
for ... of
for
loop...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
let bonusSquare = 3let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// whats our word score if we inclue bonuses?let letters = word.split('')let score = 0for (let letter of letters) { let pts = lettersPoints[letter] score += pts}console.log(`${word} is worth ${score} points!`)
we need to use standard for loop for this
for (let x of stuff) {
// something with x
}
for (start; while?; after;) {
//something with start vars
}
for (let x of stuff) {
// something with x
}
for (let i=0; i < stuff.length; i++;) {
// something with i
// generally stuff[i]
}
let score = 0for (let letter of letters) { let pts = lettersPoints[letter] score += pts}
let score = 0for (let letter of letters) { let pts = lettersPoints[letter] score += pts}
let score = 0score += 67score *= 2score -= 8score /= 3score
42
let message = 'This'message = message + ' is'if (message.length < 5) { message = message + ' helpful but'} else { message = message + ' tiring and'}message = message + ' gets annoying'message
This is tiring and gets annoying
let message = 'This'message += ' is'if (message.length < 5) { message += ' helpful but'} else { message += ' tiring and'}message += ' gets annoying'message
This is tiring and gets annoying
x++
++x
While we're at it, let's make things even faster to type!
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
repl_example("count-letters")
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) {}
02:30
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) {}// repl_example("count-letters")
write out answer, possibly with help from the audience
or skip to next slide
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) { if (letters[letter]) { letters[letter] += 1 } else { letters[letter] = 1 }}// calculate the score by letter countletters
Object.keys(letters)
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) { if (letters[letter]) { letters[letter] += 1 } else { letters[letter] = 1 }}// calculate the score by letter countlet score = 0for (let letter of Object.keys(lettersPoints)) { score += letters[letter] * lettersPoints[letter]}
rewrite both steps as functions:
countLetters(word)
tallyScore(word)
discuss scope
let word = 'syzygy'let letters = {}// here's the for loop we wrote before...for (let letter of word) { if (letters[letter]) { letters[letter] += 1 } else { letters[letter] = 1 }}letters
replace with .forEach
let word = 'syzygy'let letters = {}const addLetter = (l) => { if (letters[l]) { letters[l] += 1 } else { letters[l] = 1 }}// here's the for loop we wrote before...// for (let letter of word) {// add_letter(letter)// }word.split('').forEach(l => addLetter(l))letters
repl_example("for-loop-to-for-each")
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10} let score = 0// replace this for loop with .forEach()for (let letter of word) { score += lettersPoints[letter]}score
25
Replace the for...of
loop with .forEach()
using an arrow function.
03:00
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10}let score = 0// replace this for loop with .forEach()word.split('').forEach((l) => score += lettersPoints[l])score
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10}let score = 0// what are the points by letter of word?// I want an array of points e.g. [1, 2, 3]word.split('').forEach((l) => score += lettersPoints[l])score
Convert to .map()
to get array of points
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10}let score = 0// what are the letters in the wordconsole.log(word.split(''))// what are the points by letter of word?const getPoints = (l) => lettersPoints[l]getPoints(word.split('')[2])word.split('') .map((l) => lettersPoints[l])
repl_example("mapping-words-1")
Write one function that takes a word and returns the point values of each letter as an array.
Then use .map()
to apply this function to the array of words
.
const lettersPoints = { "a": 1, "b": 3, "c": 3, // ....}let words = ['freezer', 'jukebox']
03:00
const lettersPoints = { "a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10, " ": 0}let words = ['freezer', 'jukebox']// Write one function that takes a word and returns// the point values of each letter as an arrayfunction word2points(word) { return word}// Then use map to apply this function to the// array of words above.words.map(word2points)
repl_example("mapping-words-2")
Write another function that takes one array of numbers, e.g. [1, 2, , 3]
,
and calculates the sum of the array.
Then use .map()
again to get an array of word scores.
02:00
const lettersPoints = { "a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10, " ": 0}let words = ['freezer', 'jukebox']// Write one function that takes a word and returns// the point values of each letter as an arrayfunction word2points(word) { return word .split('') .map((l) => lettersPoints[l])}// Then use map to apply this function to the// array of words above.words.map(word2points)// Write another function that takes an array// of numbers and returns the total of these values// e.g. [1, 2, 3] => 6function score(points) { return points}words .map(word2points) .map(score)
let word = 'queue'const tiles = [ {"letter": "a", "points": 1 }, {"letter": "b", "points": 3 }, {"letter": "c", "points": 3 }, {"letter": "e", "points": 1 }, {"letter": "q", "points": 10 }, {"letter": "u", "points": 1 }] // what are the tiles for our word?
Introduce .filter()
repl_example("filter-high-points")
This time, we have an array of tiles
and each tile has a .letter
and .points
.
How many possible points values are there in Scrabble?
Use .map()
to get an array of all the point values
and then use for ... of
loop to collect unique values into an array.
Finally, use filter to get the tiles with the 3 largest point values.
const tiles = [ {"letter": "a", "points": 1 }, {"letter": "b", "points": 3 }, {"letter": "c", "points": 3 } // ...]
const tiles = [ {"letter": "a", "points": 1 }, {"letter": "b", "points": 3 }, {"letter": "c", "points": 3 }, {"letter": "d", "points": 2 }, {"letter": "e", "points": 1 }, {"letter": "f", "points": 4 }, {"letter": "g", "points": 2 }, {"letter": "h", "points": 4 }, {"letter": "i", "points": 1 }, {"letter": "j", "points": 8 }, {"letter": "k", "points": 5 }, {"letter": "l", "points": 1 }, {"letter": "m", "points": 3 }, {"letter": "n", "points": 1 }, {"letter": "o", "points": 1 }, {"letter": "p", "points": 3 }, {"letter": "q", "points": 10 }, {"letter": "r", "points": 1 }, {"letter": "s", "points": 1 }, {"letter": "t", "points": 1 }, {"letter": "u", "points": 1 }, {"letter": "v", "points": 4 }, {"letter": "w", "points": 4 }, {"letter": "x", "points": 8 }, {"letter": "y", "points": 4 }, {"letter": "z", "points": 10 }, {"letter": " ", "points": 0 }]// Which letters have the highest points?// Note that tiles is now an array of objectslet allPoints = tiles.map(tile => tile.points)let possiblePoints = []for (let pt of allPoints) { if (!possiblePoints.includes(pt)) { possiblePoints.push(pt) }}possiblePoints// Then filter tiles to have an array of just// the top 3 largest point valuestiles.filter(tile => tile.points >= 5)
const lettersPoints = { "a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10, " ": 0}let word = 'quixotic'word.split('') .map(letter => lettersPoints[letter])
.reduce((total, pts) => total + pts)
repl_example("mapping-words-3")
Rewrite the internals of score()
to use .reduce()
.
Use words.map()
and the functions to calculate an array of word points.
Then use score()
one last time to calculate the player's total score.
// replace the .forEach() method below with .reduce()function score(points) { let total = 0 points.forEach(pt => total += pt) return total}
03:00
const tiles = [ {"letter":"a","points":1},{"letter":"b","points":3},{"letter":"c","points":3},{"letter":"d","points":2},{"letter":"e","points":1},{"letter":"f","points":4},{"letter":"g","points":2},{"letter":"h","points":4},{"letter":"i","points":1},{"letter":"j","points":8},{"letter":"k","points":5},{"letter":"l","points":1},{"letter":"m","points":3},{"letter":"n","points":1},{"letter":"o","points":1},{"letter":"p","points":3},{"letter":"q","points":10},{"letter":"r","points":1},{"letter":"s","points":1},{"letter":"t","points":1},{"letter":"u","points":1},{"letter":"v","points":4},{"letter":"w","points":4},{"letter":"x","points":8},{"letter":"y","points":4},{"letter":"z","points":10},{"letter":" ","points":0}]// Earlier we found all unique point values// We can do this in one .reduce() insteadlet allPoints = tiles.map(tile => tile.points)let possiblePoints = []for (let pt of allPoints) { if (!possiblePoints.includes(pt)) { possiblePoints.push(pt) }}
// Earlier we found all unique point values// We can do this in one .reduce() insteadtiles.reduce(function(possible, tile) { if (!possible.includes(tile.points)) { possible.push(tile.points) console.log(possible, tile.points) } return possible}, [])
Okay, from here we can do a group activity...
Review event listener lifecycle
element.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
element.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
Choose the element to spy on, e.g.
const btn = document.querySelector('#easy-btn')btn.addEventListener()// or listen to all events in the documentdocument.addEventListener()
element.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
const btn = document.querySelector('#easy-btn')
btn.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
Choose the event type to listen for
const btn = document.querySelector('#easy-btn')
btn.addEventListener('click', function(event) {
// do something here ...
console.log(event)
})
The event object contains information about what happened
event | Description |
---|---|
.target | where the event happened |
.currentTarget | which element is listening |
.x, .y | x, y coordinates |
others | depending on event type |
const btn = document.querySelector('#easy-btn')
btn.addEventListener('click', function(event) {
// do something here ...
console.log(event)
})
๐คน
repl_example("browser-event-types")
repl_example("event-bubbling")
repl_example("animation-by-transition")
We take for granted the built in functions we get in R.
I've created a few exercises recreating iconic R functions.
repl_example("r-in-js")
Find a partner for pair programming.
One person chooses an exercise and is the driver and types code in their ๐ป.
The other person is the navigator (or back-seat driver) ๐.
Change roles after each exercise.
05:00
Keyboard shortcuts
โ, โ, Pg Up, k | Go to previous slide |
โ, โ, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
o | Tile View: Overview of Slides |
Esc | Back to slideshow |
Garrick Aden-Buie
rstudio::conf(2020, "JavaScript for Shiny Users")
Why Javascript | http://bit.ly/jsm_19
Why Javascript | http://bit.ly/jsm_19
Why Javascript | http://bit.ly/jsm_19
๐จ๐ผโ๐ป
repl_js()
what is scrabble?
tiles with letters, letters have points, squares have point multipliers
let myScore = 12let yourScore = 33if (true) { console.log('Yay!')}
<
>
repl_example("truthy-falsy")
Try a few of the options below to see which values are truthy and which are falsy.
true
, false
A number, e.g. 42
or 0
A number in a string, e.g. "42"
or "0"
Strings, e.g 'yes'
or 'false'
A negative number
An object and a empty object
An array and an empty array
01:30
false
0
""
null
undefined
NaN
false
0
""
null
undefined
NaN
Everything else.
42 == '42'
42 == '42'
42 === '42'
42 == '42'
โ loose equality
42 === '42'
โ strict equality
42 != '42'
42 !== '42'
let myScore = 12let yourScore = 33if (myScore > yourScore) { console.log('Yay!')} else { console.log('bummer')}
'You ' + result + '!'
1 + '1'
?const result = myScore > yourScore ? 'win' : 'lose'console.log(`You ${result}!`)
condition ? true : false
condition ? ๐ : ๐
condition ? ๐ : ๐
Is condition? then ๐ else ๐
repl_example("if-else-game-over")
Use if ... else
or the ternary if
statement to determine the outcome of the game.
Tell the player how they did.
Report the final scores and the final outcome.
Use string addition
points + ' points'`
or template strings
`${points} points`
let scores = {player: 12, opponent: 33}// What's the outcome of the game for player?if (scores.player > scores.opponent) { result = 'won'} else if (scores.player < scores.opponent) { result = 'lost'} else { result = 'tied'}// Tell the player how they didlet outcome = 'You scored: ' + scores.playeroutcome = outcome + '\nOpponent: ' + scores.opponentoutcome = outcome + '\n\nYou ' + resultconsole.log(outcome)
result
: let result = 'tied'
+=
for outcome
We've used variables to structure an object
let player = 12let opponent = 33let scores = {player: 12, opponent: 33}
scores
...is sort of the opposite.
We can destructure objects by matching variable names to key names
...is sort of the opposite.
We can destructure objects by matching variable names to key names
scores
...is sort of the opposite.
We can destructure objects by matching variable names to key names
scores
let {player, opponent} = scoresconsole.log("player: ", player)console.log("opponent: ", opponent)
const scores = {player: 12, opponent: 33}// rewrite using destructuringif (scores.player > scores.opponent) { result = 'won'} else if (scores.player < scores.opponent) { result = 'lost'} else { result = 'tied'}// Tell the player how they didlet outcome = 'You scored: ' + scores.playeroutcome = outcome + '\nOpponent: ' + scores.opponentoutcome = outcome + '\n\nYou ' + resultconsole.log(outcome)
const wordPoints = [10, 3, 7, 4]
let [first, second] = wordPointsconsole.log({ first, second })
const wordPoints = [10, 3, 7, 4]
let [first, second, ...others] = wordPointsconsole.log({ first, second, others })
...rest gets the rest of the things that weren't pulled out
let [first, second, ...others] = wordPointsconsole.log({ first, second, others })
...rest also works for objects
scores.result = 'You lost'console.log(scores)let {result, ...score} = scoresconsole.log('result: ', result)console.log(score.player)
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
What will we get if we put them together like this?
let ourPoints = [myPoints, yourPoints]ourPoints
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
If we want a flat array, we can use ...spread
let ourPoints = [...myPoints, ...yourPoints]ourPoints
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
Which is also useful when building up an array
let newPoints = 9myPoints = //________mypoints
๐ค Where do I put the dots?
...myPoints
...myPoints, ...newPoints
...newPoints
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
Which is also useful when building up an array
let newPoints = 9myPoints = [...myPoints, newPoints]myPoints
๐ค Where do I put the dots?
...myPoints
...myPoints, ...newPoints
...newPoints
...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// whats our word score?
score = 0
+=
for ... of
for
loop...spread flatens out arrays and objects
let myPoints = [3, 2, 5, 4]let yourPoints = [7, 4, 2, 8]
let bonusSquare = 3let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// whats our word score if we inclue bonuses?let letters = word.split('')let score = 0for (let letter of letters) { let pts = lettersPoints[letter] score += pts}console.log(`${word} is worth ${score} points!`)
we need to use standard for loop for this
for (let x of stuff) {
// something with x
}
for (start; while?; after;) {
//something with start vars
}
for (let x of stuff) {
// something with x
}
for (let i=0; i < stuff.length; i++;) {
// something with i
// generally stuff[i]
}
let score = 0for (let letter of letters) { let pts = lettersPoints[letter] score += pts}
let score = 0for (let letter of letters) { let pts = lettersPoints[letter] score += pts}
let score = 0score += 67score *= 2score -= 8score /= 3score
let message = 'This'message = message + ' is'if (message.length < 5) { message = message + ' helpful but'} else { message = message + ' tiring and'}message = message + ' gets annoying'message
let message = 'This'message += ' is'if (message.length < 5) { message += ' helpful but'} else { message += ' tiring and'}message += ' gets annoying'message
x++
++x
While we're at it, let's make things even faster to type!
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
x++
++x
repl_example("count-letters")
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) {}
02:30
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) {}// repl_example("count-letters")
write out answer, possibly with help from the audience
or skip to next slide
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) { if (letters[letter]) { letters[letter] += 1 } else { letters[letter] = 1 }}// calculate the score by letter countletters
Object.keys(letters)
let word = 'flyby'let lettersPoints = {b: 3, f:4, l:1, y:4}// how many of each letter in the word?let letters = {}for (let letter of word) { if (letters[letter]) { letters[letter] += 1 } else { letters[letter] = 1 }}// calculate the score by letter countlet score = 0for (let letter of Object.keys(lettersPoints)) { score += letters[letter] * lettersPoints[letter]}
rewrite both steps as functions:
countLetters(word)
tallyScore(word)
discuss scope
let word = 'syzygy'let letters = {}// here's the for loop we wrote before...for (let letter of word) { if (letters[letter]) { letters[letter] += 1 } else { letters[letter] = 1 }}letters
replace with .forEach
let word = 'syzygy'let letters = {}const addLetter = (l) => { if (letters[l]) { letters[l] += 1 } else { letters[l] = 1 }}// here's the for loop we wrote before...// for (let letter of word) {// add_letter(letter)// }word.split('').forEach(l => addLetter(l))letters
repl_example("for-loop-to-for-each")
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10} let score = 0// replace this for loop with .forEach()for (let letter of word) { score += lettersPoints[letter]}score
Replace the for...of
loop with .forEach()
using an arrow function.
03:00
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10}let score = 0// replace this for loop with .forEach()word.split('').forEach((l) => score += lettersPoints[l])score
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10}let score = 0// what are the points by letter of word?// I want an array of points e.g. [1, 2, 3]word.split('').forEach((l) => score += lettersPoints[l])score
Convert to .map()
to get array of points
let word = 'syzygy'let lettersPoints = {"g":2,"s":1,"y":4,"z":10}let score = 0// what are the letters in the wordconsole.log(word.split(''))// what are the points by letter of word?const getPoints = (l) => lettersPoints[l]getPoints(word.split('')[2])word.split('') .map((l) => lettersPoints[l])
repl_example("mapping-words-1")
Write one function that takes a word and returns the point values of each letter as an array.
Then use .map()
to apply this function to the array of words
.
const lettersPoints = { "a": 1, "b": 3, "c": 3, // ....}let words = ['freezer', 'jukebox']
03:00
const lettersPoints = { "a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10, " ": 0}let words = ['freezer', 'jukebox']// Write one function that takes a word and returns// the point values of each letter as an arrayfunction word2points(word) { return word}// Then use map to apply this function to the// array of words above.words.map(word2points)
repl_example("mapping-words-2")
Write another function that takes one array of numbers, e.g. [1, 2, , 3]
,
and calculates the sum of the array.
Then use .map()
again to get an array of word scores.
02:00
const lettersPoints = { "a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10, " ": 0}let words = ['freezer', 'jukebox']// Write one function that takes a word and returns// the point values of each letter as an arrayfunction word2points(word) { return word .split('') .map((l) => lettersPoints[l])}// Then use map to apply this function to the// array of words above.words.map(word2points)// Write another function that takes an array// of numbers and returns the total of these values// e.g. [1, 2, 3] => 6function score(points) { return points}words .map(word2points) .map(score)
let word = 'queue'const tiles = [ {"letter": "a", "points": 1 }, {"letter": "b", "points": 3 }, {"letter": "c", "points": 3 }, {"letter": "e", "points": 1 }, {"letter": "q", "points": 10 }, {"letter": "u", "points": 1 }] // what are the tiles for our word?
Introduce .filter()
repl_example("filter-high-points")
This time, we have an array of tiles
and each tile has a .letter
and .points
.
How many possible points values are there in Scrabble?
Use .map()
to get an array of all the point values
and then use for ... of
loop to collect unique values into an array.
Finally, use filter to get the tiles with the 3 largest point values.
const tiles = [ {"letter": "a", "points": 1 }, {"letter": "b", "points": 3 }, {"letter": "c", "points": 3 } // ...]
const tiles = [ {"letter": "a", "points": 1 }, {"letter": "b", "points": 3 }, {"letter": "c", "points": 3 }, {"letter": "d", "points": 2 }, {"letter": "e", "points": 1 }, {"letter": "f", "points": 4 }, {"letter": "g", "points": 2 }, {"letter": "h", "points": 4 }, {"letter": "i", "points": 1 }, {"letter": "j", "points": 8 }, {"letter": "k", "points": 5 }, {"letter": "l", "points": 1 }, {"letter": "m", "points": 3 }, {"letter": "n", "points": 1 }, {"letter": "o", "points": 1 }, {"letter": "p", "points": 3 }, {"letter": "q", "points": 10 }, {"letter": "r", "points": 1 }, {"letter": "s", "points": 1 }, {"letter": "t", "points": 1 }, {"letter": "u", "points": 1 }, {"letter": "v", "points": 4 }, {"letter": "w", "points": 4 }, {"letter": "x", "points": 8 }, {"letter": "y", "points": 4 }, {"letter": "z", "points": 10 }, {"letter": " ", "points": 0 }]// Which letters have the highest points?// Note that tiles is now an array of objectslet allPoints = tiles.map(tile => tile.points)let possiblePoints = []for (let pt of allPoints) { if (!possiblePoints.includes(pt)) { possiblePoints.push(pt) }}possiblePoints// Then filter tiles to have an array of just// the top 3 largest point valuestiles.filter(tile => tile.points >= 5)
const lettersPoints = { "a": 1, "b": 3, "c": 3, "d": 2, "e": 1, "f": 4, "g": 2, "h": 4, "i": 1, "j": 8, "k": 5, "l": 1, "m": 3, "n": 1, "o": 1, "p": 3, "q": 10, "r": 1, "s": 1, "t": 1, "u": 1, "v": 4, "w": 4, "x": 8, "y": 4, "z": 10, " ": 0}let word = 'quixotic'word.split('') .map(letter => lettersPoints[letter])
.reduce((total, pts) => total + pts)
repl_example("mapping-words-3")
Rewrite the internals of score()
to use .reduce()
.
Use words.map()
and the functions to calculate an array of word points.
Then use score()
one last time to calculate the player's total score.
// replace the .forEach() method below with .reduce()function score(points) { let total = 0 points.forEach(pt => total += pt) return total}
03:00
const tiles = [ {"letter":"a","points":1},{"letter":"b","points":3},{"letter":"c","points":3},{"letter":"d","points":2},{"letter":"e","points":1},{"letter":"f","points":4},{"letter":"g","points":2},{"letter":"h","points":4},{"letter":"i","points":1},{"letter":"j","points":8},{"letter":"k","points":5},{"letter":"l","points":1},{"letter":"m","points":3},{"letter":"n","points":1},{"letter":"o","points":1},{"letter":"p","points":3},{"letter":"q","points":10},{"letter":"r","points":1},{"letter":"s","points":1},{"letter":"t","points":1},{"letter":"u","points":1},{"letter":"v","points":4},{"letter":"w","points":4},{"letter":"x","points":8},{"letter":"y","points":4},{"letter":"z","points":10},{"letter":" ","points":0}]// Earlier we found all unique point values// We can do this in one .reduce() insteadlet allPoints = tiles.map(tile => tile.points)let possiblePoints = []for (let pt of allPoints) { if (!possiblePoints.includes(pt)) { possiblePoints.push(pt) }}
// Earlier we found all unique point values// We can do this in one .reduce() insteadtiles.reduce(function(possible, tile) { if (!possible.includes(tile.points)) { possible.push(tile.points) console.log(possible, tile.points) } return possible}, [])
Okay, from here we can do a group activity...
Review event listener lifecycle
element.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
element.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
Choose the element to spy on, e.g.
const btn = document.querySelector('#easy-btn')btn.addEventListener()// or listen to all events in the documentdocument.addEventListener()
element.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
const btn = document.querySelector('#easy-btn')
btn.addEventListener('type', function(event) {
// do something here ...
console.log(event)
})
Choose the event type to listen for
const btn = document.querySelector('#easy-btn')
btn.addEventListener('click', function(event) {
// do something here ...
console.log(event)
})
The event object contains information about what happened
event | Description |
---|---|
.target | where the event happened |
.currentTarget | which element is listening |
.x, .y | x, y coordinates |
others | depending on event type |
const btn = document.querySelector('#easy-btn')
btn.addEventListener('click', function(event) {
// do something here ...
console.log(event)
})
๐คน
repl_example("browser-event-types")
repl_example("event-bubbling")
repl_example("animation-by-transition")
We take for granted the built in functions we get in R.
I've created a few exercises recreating iconic R functions.
repl_example("r-in-js")
Find a partner for pair programming.
One person chooses an exercise and is the driver and types code in their ๐ป.
The other person is the navigator (or back-seat driver) ๐.
Change roles after each exercise.
05:00