$30 off During Our Annual Pro Sale. View Details »

Break all the Rulez

Break all the Rulez

Presented at: jsconf.eu in Berlin, Oct 6th 2012
Video: http://www.youtube.com/watch?v=MFtijdklZDo&feature=plcp

Good programmers follow best practices; great programmers investigate them.

Many JavaScript sources proclaim (with miraculous certainty) that some tricky language features are anti-patterns that must be avoided at all costs, while offering little or nothing in the way of substantive evidence beyond alarmist warnings or references to their favorite gurus. We shouldn’t ask people to follow rules that we can’t explain or propose actions that we can’t defend.

This talk will demonstrate that, whether its double-equals coercion, iteration without hasOwnProperty, augmenting native prototypes or even fraternizing with the evil ‘eval’ and ‘with’, there is a time and place for virtually every feature of JavaScript and taking the time to study and understand their potential will enrich the programming experience, just as a broader vocabulary enriches the speaking experience. The talk will feature copius real life examples drawn from respected libaries and tools.

Angus Croll

October 06, 2012
Tweet

More Decks by Angus Croll

Other Decks in Technology

Transcript

  1. bReaK aLL
    thE RuleZ
    @angustweets
    Sunday, October 7, 12

    View Slide

  2. Sunday, October 7, 12

    View Slide

  3. I work at Twitter
    We love JavaScript
    We embrace All The Parts
    We do everything in Strict Mode
    Sunday, October 7, 12

    View Slide

  4. “Please don’t do this”
    Every tech forum. Ever.
    “The subset I carved out is vastly
    superior to the language as a whole”
    Douglas Crockford - The Good Parts
    Sunday, October 7, 12

    View Slide

  5. Why are there Rules?
    Sunday, October 7, 12

    View Slide

  6. Rules help us to do it right
    But who decides what is right?
    Sunday, October 7, 12

    View Slide

  7. Right as it applies to Soup
    Sunday, October 7, 12

    View Slide

  8. What is authentic minestrone soup?
    Oh!! Google Images will know..
    Sunday, October 7, 12

    View Slide

  9. Sunday, October 7, 12

    View Slide

  10. >>>>>:-|
    Sunday, October 7, 12

    View Slide

  11. Correctness is Subjective
    Sunday, October 7, 12

    View Slide

  12. Each of us is unique.
    Each of us considers something
    harmful.
    Sunday, October 7, 12

    View Slide

  13. Sunday, October 7, 12

    View Slide

  14. Harmful is Subjective
    Sunday, October 7, 12

    View Slide

  15. Germaine de Staël (1766 - 1817)
    “Rules are only barriers to prevent
    children from falling”
    Sunday, October 7, 12

    View Slide

  16. *Andrew Dupont
    In Singapore everything runs smoothly
    but at the expense of personal freedom.
    Java is Singapore.*
    How Singapore do you want JavaScript
    to be?
    Sunday, October 7, 12

    View Slide

  17. Wikipedia Policy (2001)
    “If a rule prevents you from improving or
    maintaining Wikipedia, ignore it.”
    Sunday, October 7, 12

    View Slide

  18. How to Break the
    Rules...
    Sunday, October 7, 12

    View Slide

  19. The with statement
    Sunday, October 7, 12

    View Slide

  20. Why are you not meant to use it?
    1) accidental clobbering and implicit
    global creation.
    Sunday, October 7, 12

    View Slide

  21. var dragger = {
    increment: 1,
    direction: 'vertical',
    activationDrag: 2,
    onRelease: cleanUp
    }
    with(dragger) {
    interval = 2;
    direction = 'any';
    }
    window.interval; //2
    Sunday, October 7, 12

    View Slide

  22. Obligatory Ironic Footnote
    ES 5 strict mode's implicit global error
    would have protected against the most
    egregious aspect of with...
    Instead ES 5 strict mode
    removed with.
    Sunday, October 7, 12

    View Slide

  23. Why are you not meant to use it?
    2) cost of closure scope resolution.
    Sunday, October 7, 12

    View Slide

  24. Why are you not meant to use it?
    3) cost of late compilation
    Sunday, October 7, 12

    View Slide

  25. Why is it useful?
    1) it powers your developer tools
    Sunday, October 7, 12

    View Slide

  26. //Chrome Developer Tools
    IS._evaluateOn =
    function(evalFunction, obj, expression) {
    IS._ensureCommandLineAPIInstalled();
    expression =
    "with (window._inspectorCommandLineAPI) {\
    with (window) { " + expression + " } }";
    return evalFunction.call(obj, expression);
    }
    Sunday, October 7, 12

    View Slide

  27. Why is it useful?
    2) it replicates block scope.
    Sunday, October 7, 12

    View Slide

  28. //YES, THIS OLD CHESTNUT
    var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; i++) {
    nodes[i].onclick =
    function(e) {alert(i);}
    }
    };
    Sunday, October 7, 12

    View Slide

  29. //you could wrap it in a function scope
    var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; i++) {
    nodes[i].onclick = function(i) {
    return function(e) {alert(i);};
    }(i);
    }
    };
    Sunday, October 7, 12

    View Slide

  30. //or use 'with' to mimic block scope
    var addHandlers = function(nodes) {
    for (var i = 0; i < nodes.length; i++) {
    with ({i:i}) {
    nodes[i].onclick =
    function(e) {alert(i);}
    }
    }
    };
    Sunday, October 7, 12

    View Slide

  31. The eval statement
    Sunday, October 7, 12

    View Slide

  32. Why are you not meant to use it?
    1) code injection loophole
    Sunday, October 7, 12

    View Slide

  33. Why are you not meant to use it?
    2) prevents closure optimization
    Sunday, October 7, 12

    View Slide

  34. Why are you not meant to use it?
    3) cost of late compilation
    Sunday, October 7, 12

    View Slide

  35. Why is it useful?
    1) when there is no JSON.parse
    Sunday, October 7, 12

    View Slide

  36. “Using JavaScript’s eval is unsafe. Use a
    real JSON parser like the JSON parser
    from json.org instead.”
    Someone on Stack Overflow
    “One shouldn't use eval to parse JSON!
    Use Douglas Crockford’s json2.js script
    from json.org!”
    Someone else on Stack Overflow
    Sunday, October 7, 12

    View Slide

  37. // From JSON2.org
    if (/^[\],:{}\s]*$/
    .test(text.replace(/*regEx*/, '@')
    .replace(/*regEx*/, ']')
    .replace(/*regEx*/, ''))) {
    j = eval('(' + text + ')');
    }
    Sunday, October 7, 12

    View Slide

  38. Why is it useful?
    2) It’s how your console rolls
    Sunday, October 7, 12

    View Slide

  39. Do this in a Webkit Console or JSBin
    Sunday, October 7, 12

    View Slide

  40. “eval and with are trivialized, misused, and
    outright condemned by most JavaScript
    programmers, but when used appropriately
    they allow for the creation of some fantastic
    pieces of code that wouldn’t be possible
    otherwise”
    John Resig
    Sunday, October 7, 12

    View Slide

  41. The Function constructor
    Sunday, October 7, 12

    View Slide

  42. new Function() is not just eval in
    disguise
    Sunday, October 7, 12

    View Slide

  43. It evaluates code in a direct lexical
    child of the global scope
    Sunday, October 7, 12

    View Slide

  44. Why is it useful?
    1) Evaluated code will always run in a
    predictable scope.
    Sunday, October 7, 12

    View Slide

  45. Why is it useful?
    2) Only globals are exposed to the
    evaluated code.
    Sunday, October 7, 12

    View Slide

  46. Why is it useful?
    3) Removes closure optimization
    concerns.
    Sunday, October 7, 12

    View Slide

  47. Where is it used?
    1) jQuery’s parseJSON
    Sunday, October 7, 12

    View Slide

  48. // jQuery parseJSON
    // Logic borrowed from http://json.org/json2.js
    if (rvalidchars.test(data.replace(rvalidescape,"@")
    .replace( rvalidtokens,"]")
    .replace( rvalidbraces,""))) {
    return ( new Function( "return " + data ) )();
    }
    Sunday, October 7, 12

    View Slide

  49. Where is it used?
    2) Underscore.js string interpolation
    Sunday, October 7, 12

    View Slide

  50. //from _.template
    // If a variable is not specified,
    // place data values in local scope.
    if (!settings.variable)
    source = 'with(obj||{}){\n' + source + '}\n';
    //..
    var render = new Function(
    settings.variable || 'obj', '_', source);
    Sunday, October 7, 12

    View Slide

  51. The == operator
    Sunday, October 7, 12

    View Slide

  52. Why are you not meant to use it?
    1) coerces operands to the same type
    2) oh, that’s it actually
    Sunday, October 7, 12

    View Slide

  53. Why is it useful?
    1) coerces operands to the same type
    Sunday, October 7, 12

    View Slide

  54. Why is it useful?
    2) undefined == null
    Sunday, October 7, 12

    View Slide

  55. //this...
    if ((x === null) || (x === undefined))
    //...is logically identical to this
    if (x == null)
    Sunday, October 7, 12

    View Slide

  56. Why is it useful?
    3) when it’s bloody obvious
    Sunday, October 7, 12

    View Slide

  57. typeof thing == "function";
    myArray.length == 2;
    myString.indexOf('x') == 0;
    Sunday, October 7, 12

    View Slide

  58. Obligatory Ironic Footnote #2
    if(x) coercion is used with much less
    reticence than == coercion but is
    generally no better understood
    Text
    if ("potato") {
    "potato" == true; //false
    }
    Sunday, October 7, 12

    View Slide

  59. The Array constructor
    Sunday, October 7, 12

    View Slide

  60. new Array() is evil right?
    Sunday, October 7, 12

    View Slide

  61. But wait, this is gorgeous...
    Sunday, October 7, 12

    View Slide

  62. //From prototype.js extension of
    //String.prototype
    function times(count) {
    return count < 1 ?
    '' : new Array(count + 1).join(this);
    }
    'me'.times(10); //"memememememememememe"
    Sunday, October 7, 12

    View Slide

  63. If you enjoyed breaking these
    rules you might consider
    breaking these ones too...
    Sunday, October 7, 12

    View Slide

  64. Do not Extend Native Prototypes
    (es 5 shims are sensible)
    Always use hasOwnProperty on for/in
    (unnecessary for unextended object hashes)
    Put all var statements at the top
    (unintuitive with for loops)
    Don’t declare a function after you use it
    (useful for de-prioritizing implementation details)
    Don’t use comma as an operator
    (use multiple expressions when syntax expects one)
    Always pass the 10 argument to parseInt
    (unnecessary unless string begins with ‘0’ or ‘x’)
    Sunday, October 7, 12

    View Slide

  65. It’s OK to break a Rule if...
    Sunday, October 7, 12

    View Slide

  66. You understand why the rule exists
    and...
    Sunday, October 7, 12

    View Slide

  67. You can mitigate (or safely ignore) the
    concerns of the rulemakers
    and...
    Sunday, October 7, 12

    View Slide

  68. Breaking the rule would add value.
    Sunday, October 7, 12

    View Slide

  69. Kristine Kathryn Rusch
    “Become an expert at the rules. Then
    break them with creativity and style”
    Sunday, October 7, 12

    View Slide

  70. tl;dr
    Be Good.
    And if you can’t be good, Be Careful.
    Sunday, October 7, 12

    View Slide

  71. qwEstionZ?
    @angustweets
    Sunday, October 7, 12

    View Slide