Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First set of exercises for events & callbacks #3

Merged
merged 11 commits into from
Nov 7, 2014
Merged
57 changes: 57 additions & 0 deletions events_and_callbacks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Events and Callbacks

Working with JavaScript requires an understanding of how
[events](http://glossary.codeunion.io/event) work. Then, to write _evented_
JavaScript, you need to be familiar with the notion of a
[callback](http://glossary.codeunion.io/callback) function.

With events, you can write code that says "when this happens, run this
function". For example, a user clicks a button on your web page which makes a
modal window appear.

In both the browser and in node.js, you can write JavaScript code that _listens
for_ and _responds to_ various events.

There are three components to writing an event listener in JavaScript:

1. The event **target** (in node.js, this is called an _emitter_)
2. The **type** (or name) of the event
3. The **callback** function to run when the event happens (or _fires_)

Here is an example of an event listener that would run in the browser:

```html
<html>
<body>
<button id="click-me">Press</button>
</body>

<script type="text/javascript">
var button = document.getElementById("click-me");

button.addEventListener('click', function(evt) {
alert('You clicked me!');
});
</script>
</html>
```

In the code above, the `button` is the event **target** (the button element that
will fire the event), `'click'` is the event **type** (when the button is
clicked, it fires a this type of event), and the function

```javascript
function(evt) {
alert('You clicked me!');
}
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend using plain old EventTarget here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean. Link to the EventTarget docs? How does one use a plain EventTarget?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I had forgotten that the browser and node use different classes: http://nodejs.org/api/events.html#events_emitter_addlistener_event_listener

var events = require('events');
eventTarget = events.EventEmitter.new();
eventTarget.addListener('woah', function() {
  console.log("I know event-fu");
});

eventTarget.emit('woah');

It's probably fine to do a browser example, especially if it includes the HTML/etc. to be fully runnable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I totally didn't realize that EventTarget is not a pbulic API. My bad.


is the **callback** (the code that will run when the event is triggered).

In node.js,

## Exercises

### Level 1 - Functions that Take Functions as Inputs

* [Passing Functions to Functions](passing_functions_to_functions)
199 changes: 199 additions & 0 deletions events_and_callbacks/passing_functions_to_functions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# Passing Functions to Functions

## Exercises

### Functions as inputs? What?

Can you get functions to return values from inside other functions?

```javascript
var animalToCatTranslator = function(sentence) {
return sentence.gsub('animal', 'cat');
}

var animalToDogTranslator = function(sentence) {
return sentence.gsub('animal', 'dog');
}

var favoriteAnimal = function(animalTranslator) {
return animalTranslator("animals are the best!");
}

favoriteAnimal(__)
// should evaluate to "cats are the best"

favoriteAnimal(__)
// should evaluate to "dogs are the best"
```

Search suggestion: `pass function as argument to another function javascript`

> Functions are objects in JavaScript, which means that you can pass them as
> arguments to other functions (just make sure not to include the `()`!).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to remove the confounding word object here. Like any other data, functions can be passed as arguments to other functions.

### Functions inside of functions can take their own arguments

Can you write functions with one parameter and then pass those functions to
_another_ function?

```javascript
var conservativeSpender = function(balance) {
return balance > 100;
};

var liberalSpender = function(balance) {
return balance > 10;
};

var shouldIBuyThis = function(balance, spendingStrategy) {
if ( spendingStrategy(balance) ) {
return "Sure! I've got the money!";
} else {
return "Nope! Gotta keep my savings up!";
}
}

shouldIBuyThis(20, __);
// should evaluate to "Nope! Gotta keep my savings up!"

shouldIBuyThis(20, __);
// should evaluate to "Sure! I've got the money!"

shouldIBuyThis(__, function(balance) {
return balance > 1000;
});
// should evaluate to "Nope! Gotta keep my savings up!"

var horribleSaver = function(balance) {
return balance > 0;
};

shouldIBuyThis(__, horribleSaver);
// should evaluate to "Sure! I've got the money!"

function smarterShouldIBuyThis(cost, balance, strategy) {
var futureBalance = balance - cost;
if ( __(futureBalance) ) {
return "Sure! I've got the money!";
} else {
return "Nope! Gotta keep my savings up!"
}
}

smarterShouldIBuyThis(50, 45, horribleSaver);
// should evaluate to "Nope! Gotta keep my savings up!"
```

### Calling a function more than once with callbacks

Can you figure out how the functions below work and solve the missing pieces?

```javascript
var doItThisManyTimes = function(numberOfTimes, callbackFunction) {
for (var i = 0; i < numberOfTimes; i++) {
callbackFunction();
}
};

doItThisManyTimes(5, __() {
__.__("wow!")
});
// should print
// wow!
// wow!
// wow!
// wow!
// wow!

var each = function(array, callbackFunction) {
for (var i = 0; i < array.length; i++) {
callbackFunction(array[i]);
}
}

each([1,2,3], function(number) {
console.log(__ * 2);
});
// should print
// 2
// 4
// 6

var printQs = __(__) {
console.log('Q' * __);
}

each([1,2,3], printQs);
// should print
// Q
// QQ
// QQQ
```

Search suggestion: `callback function javascript`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit looks good.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though it may be easier for people to get "doThisXTimes" instead of iteration over an array. Maybe that could be a pre-cursor here.


> When you need to perform the some operation many times within a function,
> using a callback is an effective tool.

### Use the return value of your callbacks

Can you figure out how to write callback functions that give values back to
their "caller"?

```javascript
var map = function(array, callbackFunction) {
var mappedArray = [];
for (var i = 0; i < array.length; i++) {
var item = array[i];

mappedArray.push( __(item) );
}
return __;
}

map(["one", "two", "three"], __(__) {
__ __.toUpperCase();
});
// should evaluate to ["ONE", "TWO", "THREE"]

var square = function(__) {
__ __ * __;
};

map([4, 5, 10], square);
// should evaluate to [16, 25, 100]
```

> Pay close attention to the names of functions and their parameters.

### Doing comparisons in functions is useful for control flow

Can you figure out how the `filter` function works and write callbacks to filter
out certain elements from arrays?

```javascript
var filter = function(array, __) {
var filteredArray = [];
for (var i = 0; i < array.length; i++) {
if ( __(array[i]) === true ) {
filteredArray.push(array[i]);
}
}
return filteredArray;
}

filter([5, -2, 19, -8], function(number) {
return __ __ 0;
});
// should evaluate to [5, 19] (numbers greater than 0)

var startsWithA = __(__) {
__ __.charAt(0).toUpperCase() === 'A'
}

filter(["apple", "aardvark", "zoo", "arch", "goggles"], startsWithA);
// should evaluate to ["apple", "aardvark", "arch"]
```

> Conditionals are expressions that return boolean values. Functions can return
> an evaluated expression. Therefore...