From b5b5ebb85200c92df1eb770142594828d52522bf Mon Sep 17 00:00:00 2001 From: sunjieming Date: Wed, 12 Apr 2017 09:38:28 -0600 Subject: [PATCH] Add solutions --- src/arrays.js | 27 +++++++++++++- src/closure.js | 19 ++++++++++ src/es6.js | 97 ++++++++++++++++++++++++++++++++---------------- src/objects.js | 26 +++++++++++-- src/recursion.js | 22 +++++++++++ src/this.js | 10 +++++ 6 files changed, 165 insertions(+), 36 deletions(-) diff --git a/src/arrays.js b/src/arrays.js index 8402703..da8e7d2 100644 --- a/src/arrays.js +++ b/src/arrays.js @@ -4,34 +4,59 @@ /* eslint-disable no-unused-vars, max-len */ const each = (elements, cb) => { + for (let i = 0; i < elements.length; i++) { + cb(elements[i], i); + } // Iterates over a list of elements, yielding each in turn to the `cb` function. // This only needs to work with arrays. // based off http://underscorejs.org/#each }; const map = (elements, cb) => { + const mappedArr = []; + each(elements, item => (mappedArr.push(cb(item)))); + return mappedArr; // Produces a new array of values by mapping each value in list through a transformation function (iteratee). // Return the new array. + // return elements.map(cb); }; -const reduce = (elements, cb, memo) => { +const reduce = (elements, cb, memo = elements.shift()) => { + each(elements, (item) => { + memo = cb(memo, item); + }); + return memo; // Combine all elements into a single value going from left to right. // Elements will be passed one by one into `cb`. // `memo` is the starting value. If `memo` is undefined then make `elements[0]` the initial value. }; const find = (elements, cb) => { + for (let i = 0; i < elements.length; i++) { + if (cb(elements[i])) return elements[i]; + } + return undefined; // Look through each value in `elements` and pass each element to `cb`. // If `cb` returns `true` then return that element. // Return `undefined` if no elements pass the truth test. }; const filter = (elements, cb) => { + const filteredValues = []; + each(elements, (item) => { + if (cb(item)) filteredValues.push(item); + }); + return filteredValues; // Similar to `find` but you will return an array of all elements that passed the truth test // Return an empty array if no elements pass the truth test }; const flatten = (elements) => { + const flattenedArr = reduce(elements, (memo, item) => { + if (Array.isArray(item)) return memo.concat(flatten(item)); + return memo.concat(item); + }, []); + return flattenedArr; // Flattens a nested array (the nesting can be to any depth). // Example: flatten([1, [2], [3, [[4]]]]); => [1, 2, 3, 4]; }; diff --git a/src/closure.js b/src/closure.js index 0284314..a6d4667 100644 --- a/src/closure.js +++ b/src/closure.js @@ -3,6 +3,8 @@ /* eslint-disable no-unused-vars */ const counter = () => { + let count = 0; + return () => (++count); // Return a function that when invoked increments and returns a counter variable. // Example: const newCounter = counter(); // newCounter(); // 1 @@ -10,17 +12,34 @@ const counter = () => { }; const counterFactory = () => { + let count = 0; + return { + increment: () => (++count), + decrement: () => (--count), + }; // Return an object that has two methods called `increment` and `decrement`. // `increment` should increment a counter variable in closure scope and return it. // `decrement` should decrement the counter variable and return it. }; const limitFunctionCallCount = (cb, n) => { + let callCount = 0; + return (...args) => { + if (callCount === n) return null; + callCount++; + return cb(...args); + }; // Should return a function that invokes `cb`. // The returned function should only allow `cb` to be invoked `n` times. }; const cacheFunction = (cb) => { + const cache = {}; + return (input) => { + if (Object.prototype.hasOwnProperty.call(cache, input)) return cache[input]; + cache[input] = cb(input); + return cache[input]; + }; // Should return a funciton that invokes `cb`. // A cache (object) should be kept in closure scope. // The cache should keep track of all arguments have been used to invoke this function. diff --git a/src/es6.js b/src/es6.js index eb846ab..8866372 100644 --- a/src/es6.js +++ b/src/es6.js @@ -7,50 +7,85 @@ //---------------- // const, =>, default parameters, arrow functions default return statements using () -var food = 'pineapple'; +// var food = 'pineapple'; +// +// var isMyFavoriteFood = function(food) { +// food = food || 'thousand-year-old egg'; //This sets a default value if `food` is falsey +// return food === 'thousand-year-old egg'; +// }; +// +// var isThisMyFavorite = isMyFavoriteFood(food); -var isMyFavoriteFood = function(food) { - food = food || 'thousand-year-old egg'; //This sets a default value if `food` is falsey - return food === 'thousand-year-old egg'; -}; +// ---------------- + +const food = 'pineapple'; + +const isMyFavoriteFood = (food = 'thousand-year-old egg') => (food === 'thousand-year-old egg'); -var isThisMyFavorite = isMyFavoriteFood(food); +const isThisMyFavorite = isMyFavoriteFood(food); //---------------- -//const, class, template literals, enhanced object literals (foo: foo, -> foo,) - -var User = function(options) { - this.username = options.username; - this.password = options.password; - this.sayHi = function() { - return this.username + ' says hello!'; - }; +//const, =>, class, template literals, enhanced object literals (foo: foo, -> foo,) + +// var User = function(options) { +// this.username = options.username; +// this.password = options.password; +// this.sayHi = function() { +// return this.username + ' says hello!'; +// }; +// } +// +// var username = 'JavaScriptForever'; +// var password = 'password'; +// +// var me = new User({ +// username: username, +// password: password, +// }); + +// ---------------- + +class User { + constructor(options) { + this.username = options.username; + this.password = options.password; + } + sayHi() { + return `${this.username} says hello!`; + } } -var username = 'JavaScriptForever'; -var password = 'password'; +const username = 'JavaScriptForever'; +const pasword = 'password'; -var me = new User({ - username: username, - password: password, +const me = new User({ + username, + password, }); // ---------------- // let, const, =>, ... (spread operator) -var addArgs = function () { - var sum = 0; - for (var i = 0; i < arguments.length; i++) { - sum += arguments[i]; - } - return sum; -}; +// var addArgs = function () { +// var sum = 0; +// for (var i = 0; i < arguments.length; i++) { +// sum += arguments[i]; +// } +// return sum; +// }; +// +// var argsToCb = function (cb) { +// var args = Array.prototype.slice.call(arguments); +// return cb.apply(null, args.splice(1)); +// }; +// +// var result = argsToCb(addArgs, 1, 2, 3, 4, 5); //result should be 15 + +// ---------------- -var argsToCb = function (cb) { - var args = Array.prototype.slice.call(arguments); - return cb.apply(null, args.splice(1)); -}; +const addArgs = (...args) => (args.reduce((memo, val) => (memo + val))); -var result = argsToCb(addArgs, 1, 2, 3, 4, 5); //result should be 15 +const argsToCb = (cb, ...args) => (cb(...args)); +const result = argsToCb(addArgs, 1, 2, 3, 4, 5); /* eslint-enable */ diff --git a/src/objects.js b/src/objects.js index 43e5376..9bb9c2f 100644 --- a/src/objects.js +++ b/src/objects.js @@ -1,37 +1,55 @@ // Complete the following underscore functions. // Reference http://underscorejs.org/ for examples. -/* eslint-disable no-unused-vars */ +/* eslint-disable no-unused-vars, arrow-body-style */ const keys = (obj) => { + return Object.keys(obj); // Retrieve all the names of the object's properties. // Return the keys as strings in an array. // Based on http://underscorejs.org/#keys }; const values = (obj) => { + return Object.keys(obj).map((key) => { + return obj[key]; + }); +}; // Return all of the values of the object's own properties. // Ignore functions // http://underscorejs.org/#values -}; + const mapObject = (obj, cb) => { + Object.keys(obj).forEach(key => (obj[key] = cb(obj[key]))); + return obj; // Like map for arrays, but for objects. Transform the value of each property in turn. // http://underscorejs.org/#mapObject }; -const pairs = (obj) => { +const pairs = obj => (Object.keys(obj).map(key => ([key, obj[key]]))); // Convert an object into a list of [key, value] pairs. // http://underscorejs.org/#pairs -}; + const invert = (obj) => { + Object.keys(obj).forEach((key) => { + const newKey = obj[key]; + obj[newKey] = key; + delete obj[key]; + }); + return obj; // Returns a copy of the object where the keys have become the values and the values the keys. // Assume that all of the object's values will be unique and string serializable. // http://underscorejs.org/#invert }; const defaults = (obj, defaultProps) => { + Object.keys(defaultProps).forEach((key) => { + if (Object.prototype.hasOwnProperty.call(obj, key)) return; + obj[key] = defaultProps[key]; + }); + return obj; // Fill in undefined properties that match properties on the `defaultProps` parameter object. // Return `obj`. // http://underscorejs.org/#defaults diff --git a/src/recursion.js b/src/recursion.js index f773ee1..be97a71 100644 --- a/src/recursion.js +++ b/src/recursion.js @@ -3,16 +3,38 @@ /* eslint-disable no-unused-vars */ const nFibonacci = (n) => { + if (n <= 1) return 1; + return nFibonacci(n - 1) + nFibonacci(n - 2); // fibonacci sequence: 1 2 3 5 8 13 ... // return the nth number in the sequence }; const nFactorial = (n) => { + if (n < 1) return 1; + return n * nFactorial(n - 1); // factorial example: !5 = 5 * 4 * 3 * 2 * 1 // return the factorial of `n` }; const checkMatchingLeaves = (obj) => { + let val; + let allMatch = true; + const checkLeaves = (object) => { + Object.keys(object).forEach((key) => { + if (val === undefined && typeof key !== 'object') { + val = object[key]; + return undefined; + } + if (typeof object[key] === 'object') return checkLeaves(object[key]); + if (object[key] !== val) { + allMatch = false; + return undefined; + } + return undefined; + }); + }; + checkLeaves(obj); + return allMatch; // return true if every property on `obj` is the same // otherwise return false }; diff --git a/src/this.js b/src/this.js index b88e142..cc340a4 100644 --- a/src/this.js +++ b/src/this.js @@ -6,8 +6,13 @@ class User { constructor(options) { + this.username = options.username; + this.password = options.password; // set a username and password property on the user object that is created } + checkPassword(passwordToCompare) { + return this.password === passwordToCompare; + } // create a method on the User class called `checkPassword` // this method should take in a string and compare it to the object's password property // return `true` if they match, otherwise return `false` @@ -19,6 +24,7 @@ const me = new User({ username: 'LambdaSchool', password: 'correcthorsebatteryst const result = me.checkPassword('correcthorsebatterystaple'); // should return `true` const checkPassword = function comparePasswords(passwordToCompare) { + return this.password === passwordToCompare; // recreate the `checkPassword` method that you made on the `User` class // use `this` to access the object's `password` property. // do not modify this function's parameters @@ -30,7 +36,11 @@ const checkPassword = function comparePasswords(passwordToCompare) { // use .call, .apply, and .bind // .call +checkPassword.call(me, 'correcthorsebatterystaple'); // .apply +checkPassword.apply(me, 'correcthorsebatterystaple'); // .bind +const boundPasswordCheck = checkPassword.bind(me); +boundPasswordCheck('correcthorsebatterystaple');