diff --git a/src/arrays.js b/src/arrays.js index f24d6ef..98f138c 100644 --- a/src/arrays.js +++ b/src/arrays.js @@ -6,33 +6,73 @@ const each = (elements, cb) => { // 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 + for (let i = 0; i < elements.length; i++) { + cb(elements[i], i); + } }; const map = (elements, cb) => { // Produces a new array of values by mapping each value in list through a transformation function (iteratee). // Return the new array. + const arr = []; + each(elements, (value) => { + arr.push(cb(value)); + }); + return arr; }; const reduce = (elements, cb, 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. + let i = 0; + if (memo === undefined) { + memo = elements[0]; + i = 1; + } + for (; i < elements.length; i++) { + memo = cb(memo, elements[i]); + } + return memo; }; const find = (elements, cb) => { // 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. + for (let i = 0; i < elements.length; i++) { + if (cb(elements[i])) { + return elements[i]; + } + } + return undefined; }; const filter = (elements, cb) => { // 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 newArr = []; + for (let i = 0; i < elements.length; i++) { + if (cb(elements[i])) { + newArr.push(elements[i]); + } + } + return newArr; }; const flatten = (elements) => { // Flattens a nested array (the nesting can be to any depth). // Example: flatten([1, [2], [3, [[4]]]]); => [1, 2, 3, 4]; + let result = []; + each(elements, (elem) => { + if (Array.isArray(elem)) { + const nestedArray = flatten(elem); + result = result.concat(nestedArray); + } else { + result.push(elem); + } + }); + return result; }; /* eslint-enable no-unused-vars, max-len */ diff --git a/src/class.js b/src/class.js index 8276e29..4ef5d75 100644 --- a/src/class.js +++ b/src/class.js @@ -5,7 +5,18 @@ // Add a method called `comparePasswords`. `comparePasswords` should have a parameter // for a potential password that will be compared to the `password` property. // Return true if the potential password matches the `password` property. Otherwise return false. - +class User { + constructor(options) { + this.email = options.email; + this.password = options.password; + } + comparePasswords(potentialPassword) { + if (this.password === potentialPassword) { + return true; + } + return false; + } +} /* eslint-disable no-undef */ // Remove this comment once you write your classes. @@ -18,7 +29,24 @@ // Cat should have the property `name` that is set in the constructor and the method // `meow` that should return the string ` meowed!` where `` is the `name` // property set on the Cat instance. +class Animal { + constructor(options) { + this.age = options.age; + } + growOlder() { + return this.age + 1; + } +} +class Cat extends Animal { + constructor(options) { + super(options); + this.name = options.name; + } + meow() { + return `${this.name} meowed!`; + } +} module.exports = { User, diff --git a/src/closure.js b/src/closure.js index 4c98af0..a7def11 100644 --- a/src/closure.js +++ b/src/closure.js @@ -5,17 +5,42 @@ const counter = () => { // Example: const newCounter = counter(); // newCounter(); // 1 // newCounter(); // 2 + let count = 0; + return () => { + count++; + return count; + }; }; const counterFactory = () => { // 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. + let count = 0; + return { + increment: () => { + count++; + return count; + }, + decrement: () => { + count--; + return count; + } + }; }; const limitFunctionCallCount = (cb, n) => { // Should return a function that invokes `cb`. // The returned function should only allow `cb` to be invoked `n` times. + let count = 0; + const returnFunction = (...args) => { + if (count === n) { + return null; + } + count++; + return cb(...args); + }; + return returnFunction; }; const cacheFunction = (cb) => { @@ -25,6 +50,14 @@ const cacheFunction = (cb) => { // If the returned function is invoked with arguments that it has already seen // then it should return the cached result and not invoke `cb` again. // `cb` should only ever be invoked once for a given set of arguments. + const cache = {}; + const cached = (arg) => { + if (Object.prototype.hasOwnProperty.call(cache, arg)) { + return cache[arg]; + } + return cache[arg] = cb(arg); + }; + return cached; }; /* eslint-enable no-unused-vars */ diff --git a/src/es6.js b/src/es6.js index eb846ab..ad7802e 100644 --- a/src/es6.js +++ b/src/es6.js @@ -7,18 +7,21 @@ //---------------- // const, =>, default parameters, arrow functions default return statements using () -var food = 'pineapple'; +/* var food = 'pineapple'; */ +const 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 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; @@ -34,23 +37,36 @@ 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!`; + } +} + +const username = 'JavaScriptForever'; +const password = 'password'; // ---------------- // let, const, =>, ... (spread operator) -var addArgs = function () { - var sum = 0; - for (var i = 0; i < arguments.length; i++) { +let addArgs = function () { + let sum = 0; + for (let i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; }; -var argsToCb = function (cb) { - var args = Array.prototype.slice.call(arguments); +let argsToCb = function (cb) { + let 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 +let result = argsToCb(addArgs, 1, 2, 3, 4, 5); //result should be 15 /* eslint-enable */ diff --git a/src/objects.js b/src/objects.js index ba39c6c..8292722 100644 --- a/src/objects.js +++ b/src/objects.js @@ -5,34 +5,61 @@ const 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 + return Object.keys(obj); }; const values = (obj) => { // Return all of the values of the object's own properties. // Ignore functions // http://underscorejs.org/#values + const vals = Object.keys(obj).map((key) => { + return obj[key]; + }); + return vals; }; const mapObject = (obj, cb) => { // Like map for arrays, but for objects. Transform the value of each property in turn. // http://underscorejs.org/#mapObject + Object.keys(obj).forEach(key => (obj[key] = cb(obj[key]))); + return obj; }; const pairs = (obj) => { // Convert an object into a list of [key, value] pairs. // http://underscorejs.org/#pairs + const keyValue = (Object.keys(obj).map(key => ([key, obj[key]]))); + return keyValue; }; - const invert = (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 +// Object.keys(obj).forEach((key) => { +// const newKey = obj[key]; +// obj[newKey] = key; +// delete obj[key]; +// }); +// return obj; + Object.keys(obj).forEach((key) => { + const newKey = obj[key]; + obj[newKey] = key; + delete obj[key]; + }); + return obj; }; const defaults = (obj, defaultProps) => { // Fill in undefined properties that match properties on the `defaultProps` parameter object. // Return `obj`. // http://underscorejs.org/#defaults + Object.keys(defaultProps).forEach((key) => { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + return; + } + obj[key] = defaultProps[key]; + }); + return obj; }; /* eslint-enable no-unused-vars */ diff --git a/src/recursion.js b/src/recursion.js index a3e997e..71f7421 100644 --- a/src/recursion.js +++ b/src/recursion.js @@ -3,11 +3,19 @@ const nFibonacci = (n) => { // fibonacci sequence: 1 2 3 5 8 13 ... // return the nth number in the sequence + if (n === 0 || n === 1) { + return 1; + } + return nFibonacci(n - 1) + nFibonacci(n - 2); }; const nFactorial = (n) => { // factorial example: !5 = 5 * 4 * 3 * 2 * 1 // return the factorial of `n` + if (n === 0 || n === 1) { + return 1; + } + return n * (nFactorial(n - 1)); }; const checkMatchingLeaves = (obj) => { diff --git a/src/this.js b/src/this.js index 8ea3020..f60e4c0 100644 --- a/src/this.js +++ b/src/this.js @@ -5,10 +5,18 @@ class User { constructor(options) { // set a username and password property on the user object that is created + this.username = options.username; + this.password = options.password; } // 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` + checkPassword(passwordCheck) { + if (this.password === passwordCheck) { + return true; + } + return false; + } } const me = new User({ username: 'LambdaSchool', password: 'correcthorsebatterystaple' }); @@ -19,13 +27,21 @@ const checkPassword = function comparePasswords(passwordToCompare) { // use `this` to access the object's `password` property. // do not modify this function's parameters // note that we use the `function` keyword and not `=>` + if (this.password === passwordToCompare) { + return true; + } + return false; }; // invoke `checkPassword` on `me` by explicitly setting the `this` context // use .call, .apply, and .bind // .call +checkPassword.call(me, 'correcthorsebatterystaple'); // .apply +checkPassword.apply(me, ['correcthorsebatterystaple']); // .bind +const boundPasswordCheck = checkPassword.bind(me); +boundPasswordCheck('correcthorsebatterystaple');