-
Expressive They say something about the purpose and result of the iteration.
-
Contained They don't have side effects if used properly. All relevant stuff occurs within the callback.
-
Scoped They provide automatic function scope for each iteration which eliminates a common type of error.
-
Modular Use of callbacks encourages you to write reusable functions to pass into iterators.
Created
August 21, 2014 02:07
-
-
Save bttmly/9a3e2f3f1b86a86319f7 to your computer and use it in GitHub Desktop.
Iteration presentation
-
Each iterator has a specific return
-
Full length: .map() => array of same length as original with new values .filter() => array of subset of original array values .reduce() => result of arbitrary reduction (can be pretty much anything) .forEach() => returns nothing
-
Breakable .every() => returns true if EVERY item returns truthy from callback; exits & returns false on false .some() => exits returns true if ANY item returns truthy from callback; else returns false
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Expressive 3 | |
function timesTwo (num) { | |
return num * 2; | |
} | |
var nums = [ 1, 2, 3, 4, 5 ]; | |
// imperative mapping | |
var results = []; | |
for ( var i = 0; i < nums.length; i++ ) { | |
results.push( timesTwo( nums[i] ) ); | |
} | |
// functional mapping | |
var results = nums.map( timesTwo ); | |
// results: [ 2, 4, 6, 8, 10 ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Expressive 4 | |
function isOdd ( num ) { | |
return num % 2 === 1; | |
} | |
var nums = [ 1, 2, 3, 4, 5 ]; | |
// imperative filtering | |
var results = []; | |
for ( var i = 0; i < nums.length; i++ ) { | |
if ( isOdd( nums[i] ) ) { | |
results.push( isOdd( nums[i] ) ); | |
} | |
} | |
// functional filtering | |
var results = nums.filter( isOdd ); | |
// results: [ 1, 3, 5 ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Scope | |
// We're going to make a class that sort of extends array. | |
// here's the constructor | |
function SuperArray ( arr ) { | |
this._arr = arr.slice(); | |
} | |
// Now we need to add some methods onto its prototype. | |
// We _could_ add them one by one, but this way we can easily add more later. | |
var methods = ['push', 'pop', 'shift', 'unshift']; | |
// This won't work as expected. | |
for ( var i = 0; i < methods.length; i++ ) { | |
SuperArray.prototype[ methods[i] ] = function () { | |
return Array.prototype[ methods[i] ].apply( this._arr, arguments ); | |
}; | |
} | |
// this will work | |
methods.forEach( function ( method ) { | |
SuperArray.prototype[method] = function () { | |
return Array.prototype[method].apply( this._arr, arguments ); | |
}; | |
}); | |
// Imperative solution | |
for ( var i = 0; i < methods.length; i++ ) { | |
( function ( method ) { | |
SuperArray.prototype[method] = function () { | |
return Array.prototype[methods].apply( this._arr, arguments ); | |
}; | |
})( methods[i] ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Using .map() | |
// mapping URLs into an array of promises, and aggregating them | |
var reqUrls = ['/users/1/info', 'users/1/pic', 'users/1/likes']; | |
var promises = reqUrls.map( $.ajax ) | |
$.when.apply( $, promises ).then( function () { | |
// code here executes after all AJAX calls have resolved. | |
// arguments[0] holds result of first call, etc. | |
}); | |
// mapping the results of calling a method on each item | |
function mapInvoke ( arr, methodName ) { | |
var args = [].slice.call( arguments, 2 ); | |
return arr.map( function ( item ) { | |
return item[methodName].apply( item, args ); | |
}); | |
} | |
// var arr = [[1, 2], [3, 4], [5, 6]] | |
// mapInvoke( arr, "pop" ) | |
// => [2, 4, 6] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Using .reduce() | |
// "mapping" an object | |
// | |
function mapObject ( obj, callback ) { | |
return Object.keys( obj ).reduce( function ( acc, key ) { | |
acc[key] = callback( obj[key], key ); | |
return acc; | |
}, {} ); | |
} | |
// Vanilla DOM manipulation | |
// | |
var slice = Function.call.bind( [].slice ); | |
function children ( domNodes ) { | |
return slice( domNodes ).reduce( function ( acc, node ) { | |
return acc.concat( slice( node.children ) ); | |
}, [] ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Combining methods for complex transformations | |
function collectionFromTable ( headers, rows ) { | |
return rows.map( function ( row ) { | |
return row.reduce( function ( model, val, i ) { | |
model[ headers[i] ] = val; | |
return model; | |
}, {} ); | |
}); | |
} | |
// Exploit existing methods with composition for extra expressiveness. | |
function matches ( a, b ) { | |
return Object.keys( a ).every( function ( key ) { | |
return a[key] === b[key]; | |
}); | |
} | |
function where ( arr, obj ) { | |
return arr.filter( matches.bind( null, obj ) ); | |
} | |
// Use .some() or .every() for end-early iteration | |
function find ( arr, testFn ) { | |
var result = null | |
arr.some( function ( item, i, arr ) { | |
if ( testFn( item, i, arr ) ) return result = item; | |
}) | |
return result; | |
} | |
function findWhere ( arr, obj ) { | |
return find( arr, matches.bind( null, obj ) ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment