functional javascript

35
Functional Javascript Ben Nolan function(i){return i};

Upload: guest4d57e6

Post on 17-Dec-2014

5.648 views

Category:

Technology


1 download

DESCRIPTION

Functional javascript presentation Ben Nolan showed at railsconf europe 2007.

TRANSCRIPT

Page 1: Functional Javascript

Functional Javascript

Ben Nolan

function(i){return i};

Page 2: Functional Javascript

About me

• New Zealander living in Munich

• Blog at bennolan.com

• Developer of Behaviour.js and Groupswiki

• I promote functional-ish javascript

Page 3: Functional Javascript

Target Audience

• Intermediate javascript developers that haven’t used prototypes enumerable functions.

• People that don’t quite follow .bind and anonymous functions(){}

Page 4: Functional Javascript

Table of Contents

• Why Functional?

• Lambdas and binding

• Enumerable functions

• Examples

• Takeaways

Page 5: Functional Javascript

Why Functional?

• Many small functions - Bugs are reduced by this methodology

• Code is more self-descriptive, promotes teamwork

• Testing is simplified

Page 6: Functional Javascript

Why not functional?

• Code looks obtuse to new developers

return function(i){return this.calc(i)}.bind(this);

• Prototype’s functional extensions are slower than native loops. This is getting better in later versions of prototype.

Page 7: Functional Javascript

Anonymous functions

• Also known as Lambdas

alert(function(){ return “hello”;}());

• Simply put - it’s a function that doesn’t have a name

Page 8: Functional Javascript

Benefit of the Lambda

• Don’t have to pollute your scope with lots of function names.

function mysort(x,y){return x<=>y};ary.sort(mysort);

or

ary.sort(function(x,y){return x<>y});

Page 9: Functional Javascript

Benefit of the Lambda

• Functions have their own scope.

while(true){ var x = 5; // not locally scoped}

function(){ var x = ‘a’; // locally scoped}

• Easier to make idempotent functions - no stomping on other variables

Page 10: Functional Javascript

The bind Function

• Bind is required because Javascript doesn’t automatically call methods in the correct scope

• Bind returns an anonymous function that calls a method in the scope of the argument

• (It’s a form of currying)

Page 11: Functional Javascript

Binding to a Banana

function x(){ alert(this);}

x(); // [object Window]

y = x.bind('Banana!')

y(); // [string Banana!]

Page 12: Functional Javascript

Binding to “this”Wrong:

MyClass.prototype = { initialize : function(){ document.body.onclick = this.onclick(); }, onclick : function(){ this.doSomething(); }, doSomething : function(){ }}

Page 13: Functional Javascript

Binding to “this”Wrong:

MyClass.prototype = { initialize : function(){ document.body.onclick = this.onclick; }, onclick : function(){ this.doSomething(); }, doSomething : function(){ }}

Page 14: Functional Javascript

Binding to “this”Right:

MyClass.prototype = { initialize : function(){ document.body.onclick = this.onclick.bind(this); }, onclick : function(){ this.doSomething(); }, doSomething : function(){ }}

Page 15: Functional Javascript

Some idioms

• Smaller functions are better.

Less code means it’s easier to inspect and easier to test. Use lots of small functions.

Page 16: Functional Javascript

Some idioms

• Idempotent functions are the ideal.

ie Functions that don’t alter the dom or the properties of a object - they just return a value.

Page 17: Functional Javascript

Some idioms

• Pragmatism not idealism.

Start with dirty big functions - refactor to smaller nicer functions as you can.

Page 18: Functional Javascript

The Enumerables

• Prototype introduces ruby-ish enumerable functions to javascript.

• Convert a javascript array to an enumerable array with the $A() function.

$A([1,2,3]);

Page 19: Functional Javascript

Enumerable Example

• Old-style javascript:

function getInsidesOf(ary){ var outp = new Array; for (i in ary){outp.push(i.innerHTML);} return outp;}

(nb: this code alters the variable i in the global namespace - an easy mistake to make)

Page 20: Functional Javascript

Enumerable Example

• Using functional Javascript:

function getInsidesOf(ary){ return $A(ary).pluck(‘innerHTML’);}

Page 21: Functional Javascript

Cool enum. methods

• Invoke(methodName)invokes methodName on each elements in the array

• Pluck(propertyName)returns an array of the property gathered from each element in the array

• inGroupsOf(integer)eg: [1,2,3,4,5] -> [[1,2],[3,4],[5]]

Page 22: Functional Javascript

Enums and lambdas

• The most powerful enum methods require a function as an argument.

• You can sort, filter and order with these tools.

Page 23: Functional Javascript

Lambdas and Enum.

• Simplest example:

return $A([1,2,3,4,5]).map( function(i){ return i+1; }});

// Returns [2,3,4,5,6]

Page 24: Functional Javascript

Lambdas and Enum.

• Simplest example:

return $A([1,2,3,4,5]).map( function(i){ return i+1; }});

// Returns [2,3,4,5,6]

Create anarray with

enum extensions

Page 25: Functional Javascript

Lambdas and Enum.

• Simplest example:

return $A([1,2,3,4,5]).map( function(i){ return i+1; }});

// Returns [2,3,4,5,6]

Anonymousfunction

Page 26: Functional Javascript

Filtering Elements

• Get an array of selected checkboxes:

$$(‘input[type=checkbox]’).select(function(el){ return el.selected;});

Page 27: Functional Javascript

Filtering Elements

• $$(‘input[type=checkbox]’).select(function(el){ return el.selected;});

Get an arrayof input tags

Page 28: Functional Javascript

Filtering Elements

• $$(‘input[type=checkbox]’).select(function(el){ return el.selected;});

Call theselect

function

Page 29: Functional Javascript

Filtering Elements

• $$(‘input[type=checkbox]’).select(function(el){ return el.selected;});

Pass a function as an

argument

Page 30: Functional Javascript

Updating Elements

• Empty the innerHTML of all A elements:

$$(‘a’).each(function(el){ el.update(‘’);});

Page 31: Functional Javascript

How I structure apps

• Use OO-style classes (class.create and object.extend)

• Try and use a minimum of private properties in my classes - introspect the dom instead

• Try and use idempotent functions

Page 32: Functional Javascript

Example code

• I have a rich-text-editor written with Prototype.

• Browsers use different markup

IE Safari Mozilla

strong <span style=..> em

Page 33: Functional Javascript

Example code

• Convert bolded spans to <b> tags

$$("span").each(function(el){ if(el.getStyle('font-weight')=='bold'){ el.convertTo(‘B’); }});

Page 34: Functional Javascript

Example code

• Find an element which has the style: “display:block”

return this.getAncestors().find(function(el){ return el.getStyle('display') == 'block';});

Page 35: Functional Javascript

Take aways

• Use many small functions that are idempotent

• Use enumerable functions

• Use anonymous functions liberally

• See prototypejs.org for more information