Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Arrow functions Columbia Front-End

Arrow functions Columbia Front-End

Deep Dive - JS Arrow Functions at Columbia Front-End 2016-12-15
https://www.meetup.com/Columbia-Front-End-Meetup/events/235216205/

Mark Pedrotti

December 15, 2016
Tweet

More Decks by Mark Pedrotti

Other Decks in Programming

Transcript

  1. Read and write 
 arrow functions twitter.com/ittordepam github.com/pedrottimark 
 


    
 speakerdeck.com/pedrottimark/
 arrow-functions-columbia-front-end
  2. Let’s take a minute 
 to see the big picture


    • Where can you learn more? • What are ECMAScript and JavaScript? • How to balance reading and writing?
  3. Understanding ECMAScript 6 Nicholas C. Zakas • created ESLint •

    has written 7 books about JavaScript • was principal frontend engineer 
 for the Yahoo! home page
  4. http://exploringjs.com/ Dr. Axel Rauschmayer • organizes JS Kongress Munich •

    blogs at http://www.2ality.com/ • Exploring ES6 • Exploring ES2016 and ES2017
  5. ECMAScript is the ideal language JavaScript is the actual language

    
 in a specific version of a browser or Node.js ECMAScript 2015 is also known as 6 2016 is also known as 7 2017 and later, by year
  6. Apply the robustness principle Develop code like a defensive driver

    • Liberal in what you receive
 Fluent in what you can read • Conservative in what you send
 Confident about what you do write
  7. Can you use arrow functions? " Chrome, Edge, Firefox, Opera,

    Safari 10 # IE 11, Safari 9.1 • http://caniuse.com/ • https://kangax.github.io/compat-table/es6/
  8. The small picture 
 is a specific example 
 Apply

    functional programming
 to display the JavaScript logo in Scalable Vector Graphics
  9. Apply functional programming • map each element to something •

    join elements into one string • function that returns a function • filter only certain elements • reduce to an aggregate value
  10. We end with a string of point coordinates <!DOCTYPE svg

    PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg viewBox="0 0 1 1" xmlns="http://www.w3.org/2000/svg"> <g fill="none" stroke="#f7df1e" stroke-width="0.95"> <desc>JavaScript community logo as a stick figure</desc> <polyline id="J" points="0.5,0.460 0.5,0.875 0.25,0.875"></polyline> <polyline id="S" points="0.875,0.508 0.667,0.508 0.667,0.667 0.875,0.667 0.875,0.875 0.6,0.875"></polyline> </g> </svg>
  11. We begin with an array of point objects var pointObjectsJ

    = [ { x: 1 / 2, y: 29 / 63 }, { x: 1 / 2, y: 7 / 8 }, { x: 1 / 4, y: 7 / 8 }, ]; var pointObjectsS = [ … ];
  12. We map each object to a string var pointObjectsJ =

    [ { x: 1 / 2, y: 29 / 63 }, // '0.5,0.4603174603174603' { x: 1 / 2, y: 7 / 8 }, // '0.5,0.875' { x: 1 / 4, y: 7 / 8 }, // '0.25,0.875' ]; pointObjectsJ.map(function (point) { return point.x + ',' + point.y; }); // [ '0.5,0.4603174603174603', '0.5,0.875', '0.25,0.875' ]
  13. And then join them into one string var pointObjectsJ =

    [ { x: 1 / 2, y: 29 / 63 }, // '0.5,0.4603174603174603' { x: 1 / 2, y: 7 / 8 }, // '0.5,0.875' { x: 1 / 4, y: 7 / 8 }, // '0.25,0.875' ]; var pointsJ = pointObjectsJ.map(function (point) { return point.x + ',' + point.y; }).join(' '); // '0.5,0.4603174603174603 0.5,0.875 0.25,0.875'
  14. Read an arrow function // (input) => output // (point)

    => coordinates var toString = (point) => point.x + ',' + point.y; // Given point as object, // return coordinates as string. var toString = function (point) { return point.x + ',' + point.y; }; function toString(object) { return point.x + ',' + point.y; }
  15. Rewrite with an arrow function // (input) => output //

    (point) => coordinates var pointsJ = pointObjectsJ.map((point) => point.x + ',' + point.y ).join(' '); var pointsJ = pointObjectsJ.map(function (point) { return point.x + ',' + point.y; }).join(' ');
  16. We begin with an array of point arrays var pointArraysJ

    = [ [ 1 / 2, 29 / 63 ], [ 1 / 2, 7 / 8 ], [ 1 / 4, 7 / 8 ], ]; var pointArraysS = [ … ];
  17. We map each array to a string by + var

    pointArraysJ = [ [ 1 / 2, 29 / 63 ], // '0.5,0.4603174603174603' [ 1 / 2, 7 / 8 ], // '0.5,0.875' [ 1 / 4, 7 / 8 ], // '0.25,0.875' ]; pointArraysJ.map(function (point) { return point[0] + ',' + point[1]; }); // [ '0.5,0.4603174603174603', '0.5,0.875', '0.25,0.875' ]
  18. We map each array to a string by join var

    pointArraysJ = [ [ 1 / 2, 29 / 63 ], // '0.5,0.4603174603174603' [ 1 / 2, 7 / 8 ], // '0.5,0.875' [ 1 / 4, 7 / 8 ], // '0.25,0.875' ]; pointArraysJ.map(function (point) { return point.join(','); }); // [ '0.5,0.4603174603174603', '0.5,0.875', '0.25,0.875' ]
  19. And then join them into one string var pointArraysJ =

    [ [ 1 / 2, 29 / 63 ], // '0.5,0.4603174603174603' [ 1 / 2, 7 / 8 ], // '0.5,0.875' [ 1 / 4, 7 / 8 ], // '0.25,0.875' ]; var pointsJ = pointArraysJ.map(function (point) { return point.join(','); }).join(' '); // '0.5,0.4603174603174603 0.5,0.875 0.25,0.875'
  20. Can you write an arrow function? // (input) => output

    // (point) => coordinates var toString = … // Given point as array, // return coordinates as string. var toString = function (point) { return point.join(','); }; function toString(point) { return point.join(','); }
  21. You can write an arrow function! // (input) => output

    // (point) => coordinates var toString = (point) => point.join(','); // Given point as array, // return coordinates as string. var toString = function (point) { return point.join(','); }; function toString(point) { return point.join(','); }
  22. Can you write an arrow function? // (input) => output

    // (point) => coordinates var pointsJ = pointArraysJ.map( ).join(' '); var pointsJ = pointArraysJ.map(function (point) { return point.join(','); }).join(' ');
  23. You can write an arrow function! // (input) => output

    // (point) => coordinates var pointsJ = pointArraysJ.map((point) => point.join(',') ).join(' '); var pointsJ = pointArraysJ.map(function (point) { return point.join(','); }).join(' ');
  24. Read a function
 (number) => string // Given number, return

    string with limited precision // at most 3 digits after the decimal point. var x1 = f( 1 / 2); // '0.5' var y1 = f(29 / 63); // '0.4603174603174603' var x2 = f( 1 / 2); // '0.5' var y2 = f( 7 / 8); // '0.875'
  25. // Given number, return string with limited precision // at

    most 3 digits after the decimal point. var f = (number) => { var toFixed = number.toFixed(3); var toString = number.toString(); // default conversion return toFixed.length < toString.length ? toFixed : toString; }; var x1 = f( 1 / 2); // '0.5' var y1 = f(29 / 63); // '0.4603174603174603' var x2 = f( 1 / 2); // '0.5' var y2 = f( 7 / 8); // '0.875'
  26. Read a function that returns a function
 (nDigits) => (number)

    => string var f = fixer(3); // at most 3 digits var x1 = f( 1 / 2); // '0.5' var y1 = f(29 / 63); // '0.4603174603174603' var x2 = f( 1 / 2); // '0.5' var y2 = f( 7 / 8); // '0.875'
  27. // Given number of digits after the decimal point, return

    function // that given number, returns string with limited precision. var fixer = (nDigits) => (number) => { var toFixed = number.toFixed(nDigits); var toString = number.toString(); // default conversion return toFixed.length < toString.length ? toFixed : toString; }; var f = fixer(3); // at most 3 digits var x1 = f( 1 / 2); // '0.5' var y1 = f(29 / 63); // '0.4603174603174603' var x2 = f( 1 / 2); // '0.5' var y2 = f( 7 / 8); // '0.875'
  28. Read a function that receives a function
 (f, point) =>

    string var f = fixer(3); toString(f, [ 1 / 2, 29 / 63 ]); // '0.5,0.460' toString(f, [ 1 / 2, 7 / 8 ]); // '0.5,0.875' toString(f, [ 1 / 4, 7 / 8 ]); // '0.25,0.875'
  29. // Given function and point as array, // return coordinates

    as string with limited precision. var toString = (f, point) => point.map((coordinate) => f(coordinate)).join(','); var f = fixer(3); toString(f, [ 1 / 2, 29 / 63 ]); // [ '0.5', '0.460' ].join(',') toString(f, [ 1 / 2, 7 / 8 ]); // [ '0.5', '0.875' ].join(',') toString(f, [ 1 / 4, 7 / 8 ]); // [ '0.25', '0.875' ].join(',')
  30. We map arrays and then join them var pointArraysJ =

    [ [ 1 / 2, 29 / 63 ], // '0.5,0.460' [ 1 / 2, 7 / 8 ], // '0.5,0.875' [ 1 / 4, 7 / 8 ], // '0.25,0.875' ]; var f = fixer(3); var pointsJ = pointArraysJ.map((point) => toString(f, point) ).join(' '); // '0.5,0.460 0.5,0.875 0.25,0.875'
  31. We filter only valid points as objects var things =

    [ null, // thing '0.5,0.4603174603174603', // thing { x: '0.5' }, // thing { x: 0.5 }, // thing { x: 0.5, y: 0.4603174603174603 }, // point ]; things.filter((thing) => isPointObject(thing)); // [ { x: 0.5, y: 0.4603174603174603 } ]
  32. Can you write an arrow function? // (input) => output

    // (thing) => validity var isPointObject = … // Given unknown thing, // return is it is a point object? function isPointObject(thing) { return thing !== null && typeof thing === 'object' && typeof thing.x === 'number' && typeof thing.y === 'number'; }
  33. You can write an arrow function! // (input) => output

    // (thing) => validity var isPointObject = (thing) => thing !== null && typeof thing === 'object' && typeof thing.x === 'number' && typeof thing.y === 'number'; // Given unknown thing, // return is it is a point object? function isPointObject(thing) { return thing !== null && typeof thing === 'object' && typeof thing.x === 'number' && typeof thing.y === 'number'; }
  34. We filter only valid points as arrays var things =

    [ '0.5,0.4603174603174603', // thing [ ], // thing [ '0.5' ], // thing [ 0.5 ], // thing [ 0.5, 0.4603174603174603 ], // point ]; things.filter((thing) => isPointArray(thing)); // [ [ 0.5, 0.4603174603174603 ] ]
  35. Can you write an arrow function? // (input) => output

    // (thing) => validity // Given unknown thing, // return is it is a point array? function isPointArray(thing) { return Array.isArray(thing) && thing.length === 2 && typeof thing[0] === 'number' && typeof thing[1] === 'number'; }
  36. You can write an arrow function! // (input) => output

    // (thing) => validity var isPointArray = (thing) => Array.isArray(thing) && thing.length === 2 && typeof thing[0] === 'number' && typeof thing[1] === 'number'; // Given unknown thing, // return is it is a point array? function isPointArray(thing) { return Array.isArray(thing) && thing.length === 2 && typeof thing[0] === 'number' && typeof thing[1] === 'number'; }
  37. We reduce to get length // The length of polyline

    is sum of distances between its points. var lengthJ = pointArraysJ.reduce(lengthOfPolyline, 0); var lengthJS = pointArraysS.reduce(lengthOfPolyline, lengthJ); var pointArraysJ = [ [ 1 / 2, 29 / 63 ], [ 1 / 2, 7 / 8 ], // 0.4146825396825397 [ 1 / 4, 7 / 8 ], // 0.25 ]; // 0.6646825396825397 var pointArraysS = [ … ];
  38. Read a reducer function // The length of polyline is

    sum of distances between its points: // between each point (after the first) and the preceding point. // A reducer function has up to 4 arguments: // (valuePrevious, element, index, array) => valueNext var lengthOfPolyline = (sum, point, index, points) => index === 0 ? sum // first point has no preceding point : sum + distanceBetweenPoints(point, points[index - 1]);
  39. Read an arrow function // The distance between two points

    is square root of // sum of squares of differences between coordinates. var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( (pointA[0] - pointB[0]) ** 2 + (pointA[1] - pointB[1]) ** 2); // ** is exponentiation operator in ECMAScript 2016
  40. // The distance between two points is square root of

    // sum of squares of differences between coordinates. var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( (pointA[0] - pointB[0]) ** 2 + (pointA[1] - pointB[1]) ** 2); distanceBetweenPoints( [ 1 / 2, 29 / 63 ], [ 1 / 2, 7 / 8 ], ); // Math.sqrt(0.1719616087175611) is 0.4146825396825397
  41. We reduce to get distance // The distance between two

    points is square root of // sum of squares of differences between coordinates. var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( (pointA[0] - pointB[0]) ** 2 + (pointA[1] - pointB[1]) ** 2); // Rewrite function for any number of dimensions 1, 2, 3, … var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( pointA.reduce((sum, coordA, index) => sum + (coordA - pointB[index]) ** 2, 0)); // (pointA[index] - pointB[index]) ** 2
  42. // The distance between two points is square root of

    // sum of squares of differences between coordinates. var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( pointA.reduce((sum, coordA, index) => sum + (coordA - pointB[index]) ** 2, 0)); // For 1 dimension, index = 0 distanceBetweenPoints( [ 29 / 63 ], [ 7 / 8 ], ); // Math.sqrt(0.1719616087175611) is 0.4146825396825397
  43. // The distance between two points is square root of

    // sum of squares of differences between coordinates. var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( pointA.reduce((sum, coordA, index) => sum + (coordA - pointB[index]) ** 2, 0)); // For 2 dimensions, index = 0, 1 distanceBetweenPoints( [ 1 / 2, 29 / 63 ], [ 1 / 2, 7 / 8 ], ); // Math.sqrt(0.1719616087175611) is 0.4146825396825397
  44. // The distance between two points is square root of

    // sum of squares of differences between coordinates. var distanceBetweenPoints = (pointA, pointB) => Math.sqrt( pointA.reduce((sum, coordA, index) => sum + (coordA - pointB[index]) ** 2, 0)); // For 3 dimensions, index = 0, 1, 2 distanceBetweenPoints( [ 1 / 2, 29 / 63, 0 ], [ 1 / 2, 7 / 8, 0 ], ); // Math.sqrt(0.1719616087175611) is 0.4146825396825397
  45. Bonus 3 more concise notations 
 for functional programming •

    array destructuring • object destructuring • object literal shortcut
  46. Rewrite with array destructuring // With a similar literal notation:

    // Put together a data structure // Take apart a data structure // Given 2D point as array, return coordinates as string. var toString = (point) => point[0] + ',' + point[1]; var toString = ([ x, y ]) => x + ',' + y; var pointsJ = pointArraysJ.map(([ x, y ]) => x + ',' + y).join(' ');
  47. // Put together at right of = // with array

    literal notation var point = [ 1 / 2, 29 / 63, ]; // Put together at left of = // with array index notation var point = []; point[0] = 1 / 2; point[1] = 29 / 63; // Take apart at left of = // with array destructuring var [ x, // 1 / 2 y, // 29 / 63 ] = point; // Take apart at right of = // with array index notation var x = point[0]; // 1 / 2 var y = point[1]; // 29 / 63
  48. Rewrite with object destructuring // With a similar literal notation:

    // Put together a data structure // Take apart a data structure // Given 2D point as object, return coordinates as string. var toString = (point) => point.x + ',' + point.y; var toString = ({ x, y }) => x + ',' + y; var pointsJ = pointObjectsJ.map(({ x, y }) => x + ',' + y).join(' ');
  49. // Put together at right of = // with object

    literal notation var point = { x: 1 / 2, y: 29 / 63, }; // Put together at left of = // with object dot notation var point = []; point.x = 1 / 2; point.y = 29 / 63; // Take apart at left of = // with object destructuring var { x, // 1 / 2 y, // 29 / 63 } = point; // Take apart at right of = // with object dot notation var x = point.x; // 1 / 2 var y = point.y; // 29 / 63
  50. Rewrite with array destructuring // Given 2D points as arrays,

    return the distance between them. var distanceBetweenArrays = (pointA, pointB) => Math.sqrt((pointA[0] - pointB[0]) ** 2 + (pointA[1] - pointB[1]) ** 2); var distanceBetweenArrays = ([ xA, yA ], [ xB, yB ]) => Math.sqrt((xA - xB) ** 2 + (yA - yB) ** 2);
  51. Rewrite with object destructuring? // Given 2D points as objects,

    return the distance between them. var distanceBetweenObjects = (pointA, pointB) => Math.sqrt((pointA.x - pointB.x) ** 2 + (pointA.y - pointB.y) ** 2); // NO! Unique argument names don’t match property names x and y. var distanceBetweenObjects = ({ xA, yA }, { xB, yB }) => Math.sqrt((xA - xB) ** 2 + (yA - yB) ** 2);
  52. Rewrite with object destructuring! // Given 2D points as objects,

    return the distance between them. var distanceBetweenObjects = (pointA, pointB) => Math.sqrt((pointA.x - pointB.x) ** 2 + (pointA.y - pointB.y) ** 2); // Yes! Duplicate property names x and y have unique argument names. var distanceBetweenObjects = ({ x: xA, y: yA }, { x: xB, y: yB }) => Math.sqrt((xA - xB) ** 2 + (yA - yB) ** 2);
  53. We split a string into an array // Given string

    of points separated by space, // return array of coordinates as strings. var splitToStrings = (points) => points.split(' '); var pointsJ = '0.5,0.460 0.5,0.875 0.25,0.875'; var arrayOfStringsJ = splitToStrings(pointsJ); // [ '0.5,0.460', '0.5,0.875', '0.25,0.875' ]
  54. And then we split each element // Given function and

    string of points separated by space, // and coordinates separated by comma, return array of points. var splitToPoints = (f, points) => points.split(' ').map((point) => { var [ xString, yString ] = point.split(','); // array destructuring return f(Number(xString), Number(yString)); // return 2D point as … }); var pointsJ = '0.5,0.460 0.5,0.875 0.25,0.875'; var arrayOfPointsJ = splitToPoints(f, pointsJ); // [ f(0.5, 0.460), f(0.5, 0.875), f(0.25, 0.875) ]
  55. A function to return a point array // Given x

    and y coordinates as numbers, return point as array. var pointAsArray = (x, y) => [ x, y ]; var pointsJ = '0.5,0.460 0.5,0.875 0.25,0.875' var arrayOfPointsJ = splitToPoints(pointAsArray, pointsJ); // [ // [ 0.5, 0.460 ], // [ 0.5, 0.875 ], // [ 0.25, 0.875 ], // ]
  56. A function to return a point object // Given x

    and y coordinates as numbers, return point as object. var pointAsObject = (x, y) => ({ x: x, y: y }); // notice ({ … }) var pointsJ = '0.5,0.460 0.5,0.875 0.25,0.875' var arrayOfPointsJ = splitToPoints(pointAsObject, pointsJ); // [ // { x: 0.5, y: 0.460 }, // { x: 0.5, y: 0.875 }, // { x: 0.25, y: 0.875 }, // ]
  57. Rewrite with object literal shortcut // Given x and y

    coordinates as numbers, return point as object. var pointAsObject = (x, y) => ({ x: x, y: y }); // The shortcut requires arguments to have same names as properties. var pointAsObject = (x, y) => ({ x, y }); // When do you need parentheses? var f = (input) => { statements; }; // block var f = (input) => { statements; return something; }; // block var f = (input) => ({ properties }); // object instead of block
  58. // If variables (or arguments) // have same names as

    properties var x = 1 / 2; var y = 29 / 63; // Put together at right of = // with object literal shortcut var point = { x, y, }; // If variables // have same names as properties // Take apart at the left // with object destructuring var { x, y, } = point;
  59. Destructuring multiple return values // (inputs) => ({ outputs })

    var pointAsObject = (x, y) => ({ x, y }); // object literal shortcut var { x, y } = pointAsObject(1 / 2, 29 / 63); // object destructuring // (inputs) => [ outputs ] var pointAsArray = (x, y) => [ x, y ]; // array literal var [ x, y ] = pointAsArray(1 / 2, 29 / 63); // array destructuring