Skip to content

Commit

Permalink
Added recursion, closure, and changed order. Refactored from 8 - 12 l…
Browse files Browse the repository at this point in the history
…essons
  • Loading branch information
SunJieMing authored and SunJieMing committed Feb 6, 2018
1 parent 554f5e8 commit 80ecf80
Show file tree
Hide file tree
Showing 51 changed files with 1,024 additions and 761 deletions.
102 changes: 102 additions & 0 deletions Lesson10-JS-VII/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Lesson 10: Javascript VII (Closure)
(Attention: These are the class notes for the [Lambda School](http://www.lambdaschool.com) pre-course instruction workshop. This is meant to serve as an accompaniment to the class)

In this lesson we will cover:

* Closure

## Closure

In JavaScript functions are first-class objects. What this means is that we can use functions in a very flexible manner. You've already seen how we can assign functions to variables:

```javascript
const foo = function() {};
```

We can put functions on objects:

```javascript
const obj = {};
obj.foo = function() {};
```

We can put functions in arrays:

```javascript
const functions = [
function() {},
function() {},
];
```

We can pass functions into other functions (these are called callback functions):

```javascript
function foo(cb) {
cb();
}

foo(function() {
console.log('I am a callback function!');
});
```

And finally, we can return a function definition from a function:

```javascript
function outer() {
return function() {
console.log('hi!');
};
}

const inner = outer();
inner(); // logs 'hi'
```

The function that retuns the new function is called a "Higher Order Function" or HOF. The idea of closure is simply that `inner` that's defined up above is able to look back into `outer` for variables that it needs. It's scope chain is going to look inside of `outer` before it looks at the global scope.

Here's another example:

```javascript
function outer() {
const name = 'Ben';
return function() {
console.log(name);
};
}
const name = 'Dan';
const inner = outer();
inner(); // logs 'Ben'
```

As you can see from the example above the function `inner` is able to look back into `outer`'s scope to retrieve the `name` variable.
It looks inside of `outer` before it checks the global scope so the name that is printed is `'Ben'` instead of `'Dan'`.

This also applies to the function's parameters:

```javascript
function makeMultiplier(x) {
return function(y) {
return x * y;
}
}

const multiplyByFive = makeMultiplier(5);
const product1 = multiplyByFive(10);

const multiplyByTwo = makeMultiplier(5);
const product2 = multiplyByTwo(7);

console.log(product1); // logs 50
console.log(product2); // logs 14
```

In the example above the `x` and the `y` are both set by their respective function calls. This can be used in many interesting ways. You can make cache functions, private variables, and you can customize a function's behavior as we did in the example above. We are able to produce a custom multiplication function.


## Additional Resources:

* [Eloquent Javascript: Higher Order Functions](https://eloquentjavascript.net/05_higher_order.html)
* [Understand Closures with Ease](http://javascriptissexy.com/understand-javascript-closures-with-ease/)
* [MDN: Closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures)
11 changes: 11 additions & 0 deletions Lesson10-JS-VII/homework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Homework #JSVII

## Instructions
---
1. Feynman Writing Prompts - Write out explanations of the following concepts like you are explaining it to a 12 year old. Doing this will help you quickly discover any holes in your understanding. Ask your questions on Slack.

* Closure

2. From the top level of your `Precourse` folder, run `npm test JSVII` to run the automated tests. You will fill out the functions in `homework.js` to make the tests pass.

For more information about Lambda School's six month CS program visit: https://lambdaschool.com
29 changes: 29 additions & 0 deletions Lesson10-JS-VII/homework/homework.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Do not change any of the function names

function counter() {
// Return a function that when invoked increments and returns a counter variable.
// Example: const newCounter = counter();
// newCounter(); // 1
// newCounter(); // 2
}

function cacheFunction(cb) {
// use closure to create a cache for the cb function
// the function that you return should accept a single argument and invoke cb with that argument
// when the function you return is invoked with an argument it should save that argument and its result
// when the function you return is called again with an argument that it has seen before it should not call cb
// but should instead directly returned the previous result
// example:
// cb -> function(x) { return x * x; }
// if the function you return is invoked with 5 it would pass 5 to cb(5) and return 25
// if the function you return is invoked again with 5 it will look on an object in the closure scope
// and return 25 directly and will not invoke cb again
}

// Do not modify code below this line.
// --------------------------------

module.exports = {
counter: counter,
cacheFunction: cacheFunction,
};
46 changes: 46 additions & 0 deletions Lesson10-JS-VII/homework/tests/JSVII.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
var exercises = require('../homework');

describe('counter', () => {
it('should return a function', () => {
expect(typeof closureMethods.counter()).toBe('function');
});
it('should return 1 when the returned function is invoked', () => {
expect(closureMethods.counter()()).toBe(1);
});
it('should increment and return the number each time the function is invoked', () => {
const counterFunction = closureMethods.counter();
expect(counterFunction()).toBe(1);
expect(counterFunction()).toBe(2);
expect(counterFunction()).toBe(3);
expect(counterFunction()).toBe(4);
expect(counterFunction()).toBe(5);
});
});

describe('cacheFunction(cb)', function() {
it('should return the callback function', function() {
var cb = function() {};
expect(typeof exercises.cacheFunction(cb)).toEqual('function');
});
it('should return the callback functions result when the cached function is invoked', function() {
var cb = function(x) {
return x * 2;
};
var cachedFunction = exercises.cacheFunction(cb);
expect(cachedFunction(5)).toBe(10);
});
it('should cache function results', function() {
var cb = jest.fn();
var cachedFunction = exercises.cacheFunction(cb);
cachedFunction(true);
cachedFunction(true);
cachedFunction(true);
cachedFunction(true);
cachedFunction(true);
cachedFunction(10);
cachedFunction(10);
cachedFunction(10);
cachedFunction(10);
expect(cb).toHaveBeenCalledTimes(2);
});
});
58 changes: 58 additions & 0 deletions Lesson11-JS-VIII/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Lesson 11: Javascript VIII (Recursion)
(Attention: These are the class notes for the [Lambda School](http://www.lambdaschool.com) pre-course instruction workshop. This is meant to serve as an accompaniment to the class)

In this lesson we will cover:

* Recursion

## Recursion

In the previous assignment we discussed the flexibility that we have with functions in JavaScript. Another cool aspect about functions is that we can invoke a function from inside of itself. This is called recursion. Recursion is a type of iteration similar to `for` and `while` loops.

The code below is an example of recursion. Don't actually run this code though because it will produce an infinite loop. Just like with `for` loops, if we don't have something that stops the iteration the cyle will continue forever. In the case below the function `foo` will continue to call itself until the program crashes.

```javascript
function foo() {
foo(); // caution: this will produce an infinite loop
}
```

The same basic pieces of a `for` loop apply to a recursive function:

```javascript
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// prints 1, 2, 3, 4, 5
```

There are three parts to the code above:
1. In the code above we have a variable `i` that we will use to keep track of how many iterations we have run.
2. We also have a truth condition that needs to be checked between each iteration. The code will run as long as it is true.
3. We are moving towards a condition where the loop stops. `i++` is doing this part.

Recursion needs to use the same three parts but it is written differently.

```javascript
function looper(n) {
if (n > 5) return;
console.log(n);
looper(n + 1);
}
looper(1);
// prints 1, 2, 3, 4, 5
```

The code above will have the same result as the `for` loop used up above. It also has the same three pieces of the `for` loop as shown above.
1. `n` is the variable we are using to keep track of our iteration.
2. Instead of a truth condition that must be `true` to keep going like in our `for` loop we have a base case. The base case says "stop when `false`".
3. We move towards satisfying the base case by modifying `n`.

Everything that can be writter recursively can be written iteratively (with a `while` loop or a `for` loop). There are cases where a recursive
solution is simpler and easier to write than an iterative solution. Recursive functions are generally used when working with various data structures
like trees, linked lists, or graphs. Programming is all about tradeoffs and different approaches have different advantages. For now we recommend that
you generally stick to iteration but it is good to understand how to write recursive solutions.

## Additional Resources:

* [Eloquent Javascript: Functions](https://eloquentjavascript.net/03_functions.html) - Scroll to the section titled "Recursion"
11 changes: 11 additions & 0 deletions Lesson11-JS-VIII/homework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Homework #JSVIII

## Instructions
---
1. Feynman Writing Prompts - Write out explanations of the following concepts like you are explaining it to a 12 year old. Doing this will help you quickly discover any holes in your understanding. Ask your questions on Slack.

* Recursion

2. From the top level of your `Precourse` folder, run `npm test JSVIII` to run the automated tests. You will fill out the functions in `homework.js` to make the tests pass.

For more information about Lambda School's six month CS program visit: https://lambdaschool.com
22 changes: 22 additions & 0 deletions Lesson11-JS-VIII/homework/homework.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Do not change any of the function names

// solve these recursively

function nFactorial(n) {
// return the factorial for n
// example:
// the factorial of 3 is 6 (3 * 2 * 1)
}

function nFibonacci(n) {
// fibonacci sequence: 1 2 3 5 8 13 ...
// return the nth number in the sequence
}

// Do not modify code below this line.
// --------------------------------

module.exports = {
nFactorial: nFactorial,
nFibonacci: nFibonacci,
};
20 changes: 20 additions & 0 deletions Lesson11-JS-VIII/homework/tests/JSVIII.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
var exercises = require('../homework');

describe('nFactorial(n)', function() {
it('should return the factorial of n', function() {
expect(exercises.nFactorial(5)).toBe(120);
expect(exercises.nFactorial(15)).toBe(1307674368000);
});
});

describe('nFibonacci(n)', function() {
it('should return the nth fibonacci number', () => {
const fib1 = recursiveMethods.nFibonacci(5);
const fib2 = recursiveMethods.nFibonacci(3);
const fib3 = recursiveMethods.nFibonacci(1);
expect(fib1).toBe(8);
expect(fib2).toBe(3);
expect(fib3).toBe(1);
});
});

2 changes: 1 addition & 1 deletion Lesson8-DOM/README.md → Lesson12-DOM/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lesson 8: DOM
# Lesson 12: DOM
(Attention: These are the class notes for the [Lambda School](http://www.lambdaschool.com) pre-course instruction workshop. This is meant to serve as an accompaniment to the class)

In this lesson we will cover:
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const html = require('fs')
.readFileSync('./Lesson8-DOM/homework/index.html')
.readFileSync('./Lesson12-DOM/homework/index.html')
.toString();

document.documentElement.innerHTML = html;
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion Lesson6-HTML-CSS/README.md → Lesson2-HTML-CSS/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Lesson 6: HTML/CSS fundamentals
# Lesson 2: HTML/CSS fundamentals
(Attention: These are the class notes for the [Lambda School](http://www.lambdaschool.com) pre-course instruction workshop. This is meant to serve as an accompaniment to the class)

In this lesson we will cover:
Expand Down
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,4 @@
3. From the top level of your `Precourse` folder, run `npm run test:JSI` to run the automated tests. At first all of the tests will be broken. You will fill out the functions in `homework.js` to make the tests pass.


#### Congratulations on finishing Homework #1!

For more information about Lambda School's six month CS program visit: https://lambdaschool.com
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 80ecf80

Please sign in to comment.