From 7d4ab914d6847337d8ca06adc6d33045091ff3b2 Mon Sep 17 00:00:00 2001 From: Mei Chen Date: Wed, 10 Mar 2021 14:49:51 -0800 Subject: [PATCH 1/2] exercise syntax --- src/www/js/es-syntax/syntax.test.js | 138 +++++++++++++--------------- 1 file changed, 66 insertions(+), 72 deletions(-) diff --git a/src/www/js/es-syntax/syntax.test.js b/src/www/js/es-syntax/syntax.test.js index 2174cd4..ae6667b 100644 --- a/src/www/js/es-syntax/syntax.test.js +++ b/src/www/js/es-syntax/syntax.test.js @@ -5,14 +5,14 @@ describe('ES2015 syntax', () => { * Assume the codebase uses `let` declarations only for variables * that are reassigned. Use `const` otherwise. */ - var a = 4 - var b = [1, 2, 3] + let a = 4 + const b = [1, 2, 3] if (b.length < 4) b.push(a) expect(b).toEqual([1, 2, 3, 4]) - var a = 2 - var c = [1, a, 3] + a = 2 + const c = [1, a, 3] expect(c).toEqual([1, 2, 3]) }) }) @@ -20,7 +20,7 @@ describe('ES2015 syntax', () => { describe('loops', () => { it('rewrite the for loop to use a let variable', () => { const nums = [] - for (var i = 0; i < 3; i++) { + for (let i = 0; i < 3; i++) { nums.push(i) } expect(nums).toEqual([0, 1, 2]) @@ -31,44 +31,37 @@ describe('ES2015 syntax', () => { it('rewrite using object function shorthand', () => { const person = { name: 'Andrew', - getName: function() { return this.name } + getName() {return this.name} } expect(person.getName()).toEqual('Andrew') }) it('rewrite using object property shorthand', () => { const name = 'Andrew' - const person = { name: name } + const person = { name } expect(person.name).toEqual('Andrew') }) }) describe('functions', () => { it('rewrite the function declaration with arrow syntax', () => { + const foo = () => 'foo' expect(foo()).toEqual('foo') - - function foo() { - return 'foo' - } }) it('rewrite the function declaration, and use implicit return for anonymous function', () => { - expect(addOneToValues([1, 2, 3])).toEqual([2, 3, 4]) - expect(() => addOneToValues([])).toThrow('Values required') - function addOneToValues(xs) { if (xs.length < 1) throw new Error('Values required') // HINT: you can use an implicit return arrow function by omitting the curly brackets - return xs.map(function (x) { - return x + 1 - }) + return xs.map(x => x + 1) } + expect(addOneToValues([1, 2, 3])).toEqual([2, 3, 4]) + expect(() => addOneToValues([])).toThrow('Values required') }) it('rewrite the logic in the function to use default parameters', () => { - const getIndexOfFoo = (str) => { - const strDefault = str || '' - return strDefault.indexOf('foo') + const getIndexOfFoo = (str = '') => { + return str.indexOf('foo') } expect(getIndexOfFoo('hello foo bar')).toEqual(6) @@ -79,9 +72,7 @@ describe('ES2015 syntax', () => { describe('array spread and destructuring', () => { it('rewrite using array destructuring', () => { const favoriteThings = ['tea', 'chocolate', 'bicycles', 'mangoes'] - const tea = favoriteThings[0] - const chocolate = favoriteThings[1] - const others = favoriteThings.slice(2) + const [tea, chocolate, ...others] = favoriteThings expect(tea).toEqual('tea') expect(chocolate).toEqual('chocolate') expect(others).toEqual(['bicycles', 'mangoes']) @@ -89,22 +80,12 @@ describe('ES2015 syntax', () => { it('rewrite to use rest parameters', () => { // takes the first number, and then adds it to each value in the remaining numbers and returns an array - const addNToNumbers = function () { - const n = arguments[0] - const nums = Array.prototype.slice.call(arguments, 1) - return nums.map(val => val + n) - } + const addNToNumbers = (first, ...rest) => rest.map(num => num + first) expect(addNToNumbers(3, 1, 2, 5)).toEqual([4, 5, 8]) }) it('rewrite using spread syntax to shallow-copy an array', () => { - const copyArray = (arr) => { - const copy = [] - for (let i = 0; i < arr.length; i++) { - copy.push(arr[i]) - } - return copy - } + const copyArray = (arr) => [...arr] const arr1 = [1, 2, 3] const copy = copyArray(arr1) @@ -114,10 +95,11 @@ describe('ES2015 syntax', () => { }) it('write a function that immutably adds a new item to an array', () => { - const concat = (arr, item) => { - arr.push(item) - return arr - } + // const concat = (arr, item) => { + // arr.push(item) + // return arr + // } + const concat = (arr, item) => [...arr, item] const animals = ['cat', 'dog', 'bird'] const moarAnimals = concat(animals, 'alpaca') expect(animals === moarAnimals).toEqual(false) @@ -125,10 +107,11 @@ describe('ES2015 syntax', () => { }) it('write a function that immutably prepends a new item to an array', () => { - const prepend = (arr, item) => { - arr.unshift(item) - return arr - } + // const prepend = (arr, item) => { + // arr.unshift(item) + // return arr + // } + const prepend = (arr, item) => [item, ...arr] const animals = ['cat', 'dog', 'bird'] const moarAnimals = prepend(animals, 'alpaca') expect(moarAnimals).toEqual(['alpaca', 'cat', 'dog', 'bird']) @@ -136,34 +119,38 @@ describe('ES2015 syntax', () => { }) it('rewrite using spread syntax to duplicate the contents of an array', () => { - const duplicateArrayContents = (arr) => { - const result = [] - for (let i = 0; i < 2; i++) { - for (let j = 0; j < arr.length; j++) { - result.push(arr[j]) - } - } - return result - } + // const duplicateArrayContents = (arr) => { + // const result = [] + // for (let i = 0; i < 2; i++) { + // for (let j = 0; j < arr.length; j++) { + // result.push(arr[j]) + // } + // } + // return result + // } + const duplicateArrayContents = (arr) => [...arr, ...arr] expect(duplicateArrayContents([1, 2, 3])).toEqual([1, 2, 3, 1, 2, 3]) }) it('CHALLENGE: rewrite using spread syntax to duplicate and reverse contents of an array', () => { // HINT: You can immutably reverse an array with: `[...array].reverse()` - const duplicateAndReverseArrayContents = (arr) => { - const result = [] - for (let i = 0; i < 2; i++) { - for (let j = 0; j < arr.length; j++) { - if (i === 0) { - result.push(arr[j]) - } else { - result.push(arr[arr.length - 1 - j]) - } - } - } - return result - } + // const duplicateAndReverseArrayContents = (arr) => { + // const result = [] + // for (let i = 0; i < 2; i++) { + // for (let j = 0; j < arr.length; j++) { + // if (i === 0) { + // result.push(arr[j]) + // } else { + // result.push(arr[arr.length - 1 - j]) + // } + // } + // } + // return result + // } + + // TODO: const duplicateAndReverseArrayContents = (arr) => [...arr, ...[...arr].reverse()] + const duplicateAndReverseArrayContents = (arr) => [...arr, arr.reverse()] expect(duplicateAndReverseArrayContents([1, 2, 3])).toEqual([1, 2, 3, 3, 2, 1]) }) @@ -174,23 +161,30 @@ describe('ES2018 syntax', () => { describe('object spread and destructuring', () => { it('rewrite using object destructuring', () => { const person = { id: 42, name: 'Andrew', location: 'Seattle' } - const id = person.id - const name = person.name - const location = person.location + // const id = person.id + // const name = person.name + // const location = person.location + + // WRONG: [id, name, location] = {person} + const {id, name, location} = person expect(id).toEqual(42) expect(name).toEqual('Andrew') expect(location).toEqual('Seattle') }) it('rewrite using object spread and destructuring', () => { + // TODO const withoutKey = (keyToRemove, obj) => { - const copy = {} - for (const [key, value] of Object.entries(obj)) { - if (key !== keyToRemove) copy[key] = value - } + // const copy = {} + // for (const [key, value] of Object.entries(obj)) { + // if (key !== keyToRemove) copy[key] = value + // } + const copy = {...obj} + delete copy[keyToRemove] return copy } + const person = { id: 42, name: 'Andrew', location: 'Seattle' } expect(withoutKey('id', person)).toEqual({ name: 'Andrew', location: 'Seattle' }) expect(withoutKey('location', person)).toEqual({ id: 42, name: 'Andrew' }) From 97a8c6594ecae734b79e5cc74b23c2424ce812f4 Mon Sep 17 00:00:00 2001 From: Mei Chen Date: Thu, 11 Mar 2021 10:06:34 -0800 Subject: [PATCH 2/2] exercises --- src/www/js/es-syntax/syntax.test.js | 5 +- src/www/js/functional/array.test.js | 75 +++++++++++++++++------------ src/www/js/this/this.test.js | 16 +++--- 3 files changed, 56 insertions(+), 40 deletions(-) diff --git a/src/www/js/es-syntax/syntax.test.js b/src/www/js/es-syntax/syntax.test.js index ae6667b..91bd987 100644 --- a/src/www/js/es-syntax/syntax.test.js +++ b/src/www/js/es-syntax/syntax.test.js @@ -149,8 +149,9 @@ describe('ES2015 syntax', () => { // return result // } - // TODO: const duplicateAndReverseArrayContents = (arr) => [...arr, ...[...arr].reverse()] - const duplicateAndReverseArrayContents = (arr) => [...arr, arr.reverse()] + const duplicateAndReverseArrayContents = (arr) => [...arr, ...[...arr].reverse()] + // WRONG: this will reverse the original arr! + //const duplicateAndReverseArrayContents = (arr) => [...arr, arr.reverse()] expect(duplicateAndReverseArrayContents([1, 2, 3])).toEqual([1, 2, 3, 3, 2, 1]) }) diff --git a/src/www/js/functional/array.test.js b/src/www/js/functional/array.test.js index 5c6e0a6..49290a1 100644 --- a/src/www/js/functional/array.test.js +++ b/src/www/js/functional/array.test.js @@ -9,9 +9,10 @@ describe('Array higher-order functions', () => { it('rewrite the for loop with forEach', () => { const mockFn = jest.fn() - for (let i = 0; i < users.length; i++) { - mockFn(users[i]) - } + // for (let i = 0; i < users.length; i++) { + // mockFn(users[i]) + // } + users.forEach(mockFn) expect(mockFn.mock.calls.length).toEqual(3) expect(mockFn.mock.calls).toEqual([ @@ -24,29 +25,31 @@ describe('Array higher-order functions', () => { describe('#filter', () => { it('rewrite the filter operation without a for loop', () => { - const usersWithFavoriteColorBlue = [] + // const usersWithFavoriteColorBlue = [] - for (let i = 0; i < users.length; i++) { - const user = users[i] - if (user.favoriteColor === 'blue') { - usersWithFavoriteColorBlue.push(user) - } - } + // for (let i = 0; i < users.length; i++) { + // const user = users[i] + // if (user.favoriteColor === 'blue') { + // usersWithFavoriteColorBlue.push(user) + // } + // } + const usersWithFavoriteColorBlue = users.filter(user => user.favoriteColor === 'blue') expect(usersWithFavoriteColorBlue).toEqual([users[0]]) }) it('write a function #reject that does the opposite of #filter and uses that method', () => { + // const reject = (pred, array) => { + // const result = [] + // for (let i = 0; i < array.length; i++) { + // if (!pred(array[i])) { + // result.push(array[i]) + // } + // } const reject = (pred, array) => { - const result = [] - for (let i = 0; i < array.length; i++) { - if (!pred(array[i])) { - result.push(array[i]) - } - } + let result = array.filter(elem => !pred(elem)) return result } - const usersWithoutFavoriteColorblue = reject(user => user.favoriteColor === 'blue', users) expect(usersWithoutFavoriteColorblue).toEqual([users[1], users[2]]) }) @@ -55,9 +58,14 @@ describe('Array higher-order functions', () => { describe('#every', () => { it('implement the #every method', () => { // === Uncomment me and implement === - // Array.prototype.every = function(pred) { - // console.log(this) // access the array with `this` - // } + Array.prototype.every = function(pred) { + // console.log(this) // access the array with `this` + let result = true + this.forEach(elem => { + if(!pred(elem)) result = false + }) + return result + } expect([1, 2, 3].every(x => x > 0)).toEqual(true) expect([1, 2, 3].every(x => x > 2)).toEqual(false) }) @@ -66,9 +74,14 @@ describe('Array higher-order functions', () => { describe('#some', () => { it('implement the #some method', () => { // === Uncomment me and implement === - // Array.prototype.some = function(pred) { - // console.log(this) // access the array with `this` - // } + Array.prototype.some = function(pred) { + // console.log(this) // access the array with `this` + let result = false + this.forEach(elem => { + if(pred(elem)) result = true + }) + return result + } expect([1, 2, 3].some(x => x > 2)).toEqual(true) expect([1, 2, 3].some(x => x > 4)).toEqual(false) }) @@ -76,14 +89,16 @@ describe('Array higher-order functions', () => { describe('#map', () => { it('rewrite using #map', () => { - const incrementAgeOfHumans = (humans) => { - const result = [] - for (let i = 0; i < humans.length; i++) { - result.push({ ...humans[i], age: humans[i].age + 1 }) - } - return result - } + // const incrementAgeOfHumans = (humans) => { + // const result = [] + // for (let i = 0; i < humans.length; i++) { + // result.push({ ...humans[i], age: humans[i].age + 1 }) + // } + // return result + // } + // TODO + const incrementAgeOfHumans = (humans) => humans.map(human => human.age + 1) expect(incrementAgeOfHumans(users)).toEqual([ { id: 1, name: 'Andrew', age: 34, favoriteColor: 'blue' }, { id: 2, name: 'Billy', age: 21, favoriteColor: 'red' }, diff --git a/src/www/js/this/this.test.js b/src/www/js/this/this.test.js index 7c2be75..c291ab1 100644 --- a/src/www/js/this/this.test.js +++ b/src/www/js/this/this.test.js @@ -1,8 +1,10 @@ describe('this', () => { it('EXERCISE 1: should give an age and an function #isAdult which checks if age is >= 18', () => { const person = { - age: 18, - isAdult() {} // TODO + age: 17, + isAdult() { + return this.age >= 18 + } } expect(person.isAdult()).toEqual(false) @@ -11,7 +13,7 @@ describe('this', () => { it('EXERCISE 2: fix getColor so it uses contextual scope', () => { const c = { color: 'green', - getColor: () => { // TODO + getColor() { return this.color } } @@ -23,9 +25,7 @@ describe('this', () => { const greeter = { message: 'Hello', print() { - function otherFn() { // TODO - expect(this.message).toEqual('Hello') - } + const otherFn = () => expect(this.message).toEqual('Hello') otherFn() } @@ -42,13 +42,13 @@ describe('this', () => { } } - const getColorFn = a.getColor // TODO + const getColorFn = a.getColor.bind(a) expect(getColorFn()).toEqual('red') }) it('EXTRA CREDIT: fix this code', () => { - const getAge = () => this.age + const getAge = function() {return this.age} const p1 = { age: 42,