1 of 21

FrontEndParty

Vanquishing Candyman

George Mauer

@togakangaroo

2 of 21

A story

3 of 21

Don't Say Candyman

//This is a forbidden function//don't call it 5 times!var sayCandyman = function() { � console.log("candyman");}���//But then some teenagers did...for(var i=0; i<5; i+=1)� sayCandyman();

4 of 21

But first let's talk functions

5 of 21

Two main ways to declare a function

function greet(whom, greeting) {return "Hi " + whom + ", " + greeting;}

=

var greet = function(whom, greeting) {return "Hi " + whom + ", " + greeting;}

6 of 21

You can return functions

function sayWelcome() {var welcomeFn = function(whom) {return “Welcome” + whom;}

return welcomeFn;}��var welcome = sayWelcome();�console.log( welcome("FrontEndParty") );

7 of 21

And now for some callback soup

8 of 21

Callback Soup - Getting into trouble

$('#females').click(function() {� list.empty();� people� .filter(function(p) { return p.gender == 'F' }).forEach(function(p) { list.append('<li>'+p.name+'</li>') })� $('button').prop('disabled', false);� $(this).prop('disabled', true);});� � $('#males').click(function() {� list.empty();� people� .filter(function(p) { return p.gender == 'M' }).forEach(function(p) { list.append('<li>'+p.name+'</li>') })� $('button').prop('disabled', false);� $(this).prop('disabled', true);});

9 of 21

Callback Soup - Cleansed

$('#females').click(function() {� showGender(this, 'F');});� � $('#males').click(function() {� showGender(this, 'M');});� � function showGender(thisButton, gender) { � list.empty();� people� .filter(function(p) { return p.gender == gender }).forEach(function(p) { list.append('<li>'+p.name+'</li>') })� $('button').prop('disabled', false);� $(thisButton).prop('disabled', true);}

10 of 21

Not bad, but we want beautiful code

11 of 21

Callback Soup - Scoured

$('#females').click(showGender('F'));� � $('#males').click(showGender('M'));

function showGender(gender) { return function() {� list.empty();� people� .filter(function(p) { return p.gender == gender }).forEach(function(p) { list.append('<li>'+p.name+'</li>') })� $('button').prop('disabled', false);� $(this).prop('disabled', true);} }

12 of 21

preventDefault is Annoying

$('#show-1').click(function(e) { � e.preventDefault();� $('.form-part').slideUp();� $('#form-part-1').slideDown() ;});

13 of 21

preventDefault is Annoying

Fixed it for you:

http://jsbin.com/adegup/2/edit

function preventDefault(fn){ return function(e) {� e && e.preventDefault && e.preventDefault();� fn.apply(this, arguments);} };

14 of 21

But back to our story

15 of 21

Don't Say Candyman

//This is a forbidden function//don't call it 5 times!var sayCandyman = function() { � console.log("candyman");}���//But then some teenagers did...for(var i=0; i<5; i+=1)� sayCandyman();

16 of 21

Don't Say Candyman

function maxTimes(maxCount, fn) {var lastResult, callCount = 0;return function maxTimes() {if(callCount >= maxCount)return lastResult;� callCount +=1;� lastResult = fn.apply(this, arguments);return lastResult;}

Functions to the rescue: http://jsbin.com/ezigug/1/edit

17 of 21

Don't Say Candyman

function maxTimes(maxCount, fn) {var lastResult, callCount = 0;return function maxTimes() {if(callCount >= maxCount)return lastResult;� callCount +=1;� lastResult = fn.apply(this, arguments);return lastResult;}

Functions to the rescue: http://jsbin.com/ezigug/1/edit

18 of 21

Underscore Has Lots of These

19 of 21

Some real code

$(document).on('keydown',

runWhen(isPressedCtrl("P"), preventDefault(toPdf)) )�$(document).on('keydown',

runWhen(isPressedCtrl("F"), preventDefault(fullScreenSlide)) )

20 of 21

Some real code

$(document).on('keydown',

runWhen(isPressedCtrl("P"), preventDefault(toPdf)) )�$(document).on('keydown',

runWhen(isPressedCtrl("F"), preventDefault(fullScreenSlide)) )

//...�function isPressedCtrl(key){var keyCode = key.charCodeAt(key);return function isPressedCtrl(e){return e && e.ctrlKey && e.which === keyCode;}}

function runWhen(filterFn, fn) { return function() {if( filterFn.apply(this, arguments) )� fn.apply(this, arguments);} }

21 of 21

Article by Raganwald

George Mauer

@togakangaroo