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

Parlez-Vous JavaScript

Angus Croll
November 30, 2012

Parlez-Vous JavaScript

You can spot the tourists a mile away. In Singapore they’re the ones drinking slings at the Raffle’s Long Bar; in JavaScript they’re the ones stuffing their favourite paradigms into a language that never needed them and works better without them.

In this talk, your humble tour guide will wander the back alleys of JavaScript in search of native patterns, uncovering the idioms that work with the language instead of fighting it. We’ll visit some fabulous local haunts: mixins, functional expressions, context injection and of course closures, while trying not to make fun of the garish tourist traps (classes, are you listening?)

Angus Croll

November 30, 2012
Tweet

More Decks by Angus Croll

Other Decks in Technology

Transcript

  1. Parlez-vous
    JavaScript?
    @angustweets

    View Slide

  2. View Slide

  3. I work at Twitter.
    We work with JavaScript.
    Not against it.

    View Slide

  4. “The grain tells you which way
    the wood wants to be cut”
    Charles Miller
    fishbowl.pastiche.org

    View Slide

  5. Episode 1
    The Accidental Tourist

    View Slide

  6. The Problem

    View Slide

  7. (weird shit)
    JAVA!!
    But Easier!!
    (Deceptively
    Familiar Syntax)
    (weird shit)
    WTF?

    View Slide

  8. JavaScript
    Ruby
    Python
    Java
    Shell
    PHP
    C
    C++
    21%
    13%
    8%
    8%
    8%
    7%
    6%
    4%
    github.com/languages

    View Slide

  9. If languages were vacation destinations,
    JavaScript would be Paris

    View Slide

  10. How not to pack for JavaScript

    View Slide

  11. C++
    RUBY
    JavaScript
    To:

    View Slide

  12. JavaScript
    To:
    strong
    typing
    static
    ‘this’
    second
    class
    functions OOP

    View Slide

  13. Episode 2
    Do as the Locals Do...

    View Slide

  14. The Five Hills of JavaScript...

    View Slide

  15. closures
    first-class
    functions
    dynamic
    ‘this’
    prototypes
    call/apply

    View Slide

  16. Episode 3
    OOP not spoken here

    View Slide

  17. OK, I lied
    Constructor-Prototype chaining* is
    OOP
    *having one custom prototype extend another

    View Slide

  18. But it’s awkward and unnatural...

    View Slide

  19. var Animal = function(gender, says) {
    this.gender = gender;
    this.says = says;
    };
    var WalkingAnimal = function(gender, says)
    {
    Animal.call(this, gender, says);
    }
    WalkingAnimal.prototype = new Animal();

    View Slide

  20. Object.create liberates prototype
    chaining from constructors.

    View Slide

  21. var animalProto = {
    speak: function() {
    console.log(this.says);
    }
    }
    var walkingAnimalProto = Object.create(
    animalProto, {
    walk: {
    value: function() {
    console.log('walking');
    }
    }
    //...
    }
    );

    View Slide

  22. ES 6 is giving us class.
    Some libraries have there own versions.

    View Slide

  23. //Prototype.js
    var SwimmingAnimal = Class.create(Animal, {
    type: 'SwimmingAnimal',
    speak: function($super) {
    return $super() + ", glug";
    }
    });
    //Dustin Diaz's "klass"
    var Alien = SuperHuman.extend({
    beam: function() {
    this.supr();
    // beam into space
    }
    });

    View Slide

  24. Do you even want classes?

    View Slide

  25. Animal
    Walking Animal
    Swimming Animal
    Flying Animal
    Cat
    Elephant
    Crocodile
    Whale
    Eagle
    Bat
    Egg-laying Animal
    Migrating Animal

    View Slide

  26. Animal
    Walking Animal
    Swimming Animal
    Flying Animal
    Cat
    Elephant
    Crocodile
    Whale
    Eagle
    Bat
    Egg-laying Animal
    Migrating Animal
    WTF? I walk
    too!!

    View Slide

  27. Migrating Animal
    Egg-laying Animal
    Flying Animal
    Swimming Animal
    Walking Animal
    Duck?
    Animal
    Cat
    Elephant
    Crocodile
    Whale
    Eagle
    Bat

    View Slide

  28. This hierarchy monster is not fussy
    es6 class
    Object.create
    class framework
    new Constructor

    View Slide

  29. However.

    View Slide

  30. The sad thing is that anyone even cares
    about inheritance hierarchies...
    Because in JavaScript they’re quite
    unnecessary...

    View Slide

  31. Episode 4
    JavaScript Mixins

    View Slide

  32. Property Copy Mixins...

    View Slide

  33. var withWalking = {
    walk: function() {
    console.log('walking');
    },
    turn: function(direction) {
    console.log('turning', direction);
    },
    stopWalking: function() {
    console.log('stopped walking');
    }
    };

    View Slide

  34. var extend = function(destination, source) {
    for (var k in source) {
    if (source.hasOwnProperty(k)) {
    destination[k] = source[k];
    }
    }
    return destination;
    };
    extend(Crocodile.prototype, withWalking);
    extend(Crocodile.prototype, withSwimming);

    View Slide

  35. Functional Mixins...

    View Slide

  36. var withWalking = function() {
    this.walk = function() {
    console.log('walking');
    };
    this.turn = function(direction) {
    console.log('turning', direction);
    };
    this.stopWalking = function() {
    console.log('stopped walking');
    };
    };

    View Slide

  37. function Crocodile(name, gender) {
    this.name = name;
    this.gender = gender;
    };
    Crocodile.prototype.stalkTourists =
    function() {
    //..
    };
    withWalking.call(Crocodile.prototype);
    withSwimming.call(Crocodile.prototype);

    View Slide

  38. Episode 5
    Monkey Patching:
    The Good Parts

    View Slide

  39. https://twitter.com/rockstar_/status/147367323488108544

    View Slide

  40. Q. How do you patch a 3rd party library
    without touching it?

    View Slide

  41. A. Wrap it.

    View Slide

  42. // Using underscore
    _.each = _.wrap(_.each,
    function(each, collection, fn, context) {
    each(collection, fn, context);
    return collection;
    }
    );
    _.each([1,2,3], alert); //[1,2,3]

    View Slide

  43. Also, why are you still using
    underscore when there’s...

    View Slide

  44. github.com/kriskowal/es5-shim

    View Slide

  45. Episode 6
    Functional

    View Slide

  46. High Order Functions

    View Slide

  47. var fruit = ["grape ", "pear ", "apple"];
    var result = [];
    for (var i = 0; i < fruit.length; i++) {
    result.push(fruit[i].trim());
    }
    result; //["grape", "pear", "apple"]

    View Slide

  48. fruit.map(function(each) {
    return each.trim();
    });

    View Slide

  49. function globalize(methodName) {
    return function(obj) {
    return obj[methodName]();
    }
    }

    View Slide

  50. fruit.map(function(each) {
    return each.trim();
    });

    View Slide

  51. fruit.map(globalize('trim'));

    View Slide

  52. Currying* (partial application)
    *yes I know it’s not technically currying

    View Slide

  53. add
    curry
    7
    .curry(7)
    var add7=
    add7(5); //12
    add(x,y)
    5
    7

    View Slide

  54. Function.prototype.curry = function() {
    if (arguments.length < 1) {
    //nothing to curry with - return function
    return this;
    }
    var method = this;
    var args = [].slice.call(arguments);
    return function() {
    return method.apply(
    this, args.concat([].slice.call(arguments)));
    }
    }

    View Slide

  55. Function Composition

    View Slide

  56. Math.pow
    alert

    View Slide

  57. alert( )
    Math.pow Math.pow
    var alertPower = alert.compose(Math.pow);

    View Slide

  58. Function.prototype.compose = function(argFunction) {
    var invokingFunction = this;
    return function() {
    return invokingFunction.call(
    this,argFunction.apply(this,arguments));
    }
    }

    View Slide

  59. Currying + Composition =

    View Slide

  60. var sliceToRegEx = ''.slice.curry(0).compose(''.search);
    var parseAlpha = sliceToRegEx.curry(/[^ a-zA-Z]/);
    parseAlpha("[email protected]") //"fredfrith"

    View Slide

  61. Episode 7
    Beware of imitations...

    View Slide

  62. San Francisco is great etc. But...

    View Slide

  63. San Francisco is great etc. But...
    its fire hydrants are non-standard

    View Slide

  64. EveryOther
    Fire Dept.
    wtf.sf?!
    SFFD
    X

    View Slide

  65. jQuery is great etc. But...

    View Slide

  66. jQuery is great etc. But...
    it’s objects are non-standard

    View Slide

  67. //jQuery selectors return jQuery objects
    var anchors = $('a');
    Array.isArray(anchors); //false

    View Slide

  68. //jQuery selectors return jQuery objects
    var anchors = $('a');
    Array.isArray(anchors); //false
    anchors.push; //function push() { [native code] }
    anchors.forEach; //undefined

    View Slide

  69. //jQuery selectors return jQuery objects
    var anchors = $('a');
    Array.isArray(anchors); //false
    anchors.push; //function push() { [native code] }
    anchors.forEach; //undefined
    //which means we are stuck in jquery land
    var hrefs = anchors.map(
    function(i, elem) {return elem.href}
    ); !!

    View Slide

  70. //jQuery selectors return jQuery objects
    var anchors = $('a');
    Array.isArray(anchors); //false
    anchors.push; //function push() { [native code] }
    anchors.forEach; //undefined
    //which means we are stuck in jquery land
    var hrefs = anchors.map(
    function(i, elem) {return elem.href}
    );
    //perpetually
    Array.isArray(hrefs); //false ;-(
    !!

    View Slide

  71. Unless you do this...

    View Slide

  72. var anchors = $('a');
    Array.isArray(anchors); //false
    hrefs = [].map.call(anchors,
    function(elem) {return elem.href}
    );
    Array.isArray(hrefs); //true
    :)

    View Slide

  73. or this...

    View Slide

  74. var anchors = $('a');
    Array.isArray(anchors); //false
    var anchors = [].slice.call(anchors);
    Array.isArray(anchors); //true

    View Slide

  75. Episode 8
    Everyday JavaScript

    View Slide

  76. you could do this...

    View Slide

  77. function getEventTarget(evt) {
    if (!evt) {
    evt = window.event;
    }
    if (!evt) {
    return;
    }
    var target;
    if (evt.target) {
    target = evt.target;
    } else {
    target = evt.srcElement;
    }
    return target;
    }

    View Slide

  78. or you could do this...

    View Slide

  79. function getEventTarget(evt) {
    evt = evt || window.event;
    return evt && (evt.target || evt.srcElement);
    }

    View Slide

  80. Episode 9
    Too long; fell asleep?

    View Slide

  81. “Every language has its own way. Follow
    its form. Don’t try to program as if you
    were using another language.”
    Marijn Haverbeke
    Eloquent JavaScript

    View Slide

  82. Questions?
    @angustweets
    speakerdeck.com/anguscroll/parlez-vous-javascript

    View Slide