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.

52c6174ba60557536f93809b4e95d97c?s=128

Angus Croll

October 06, 2012
Tweet

Transcript

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

  2. Sunday, October 7, 12

  3. I work at Twitter We love JavaScript We embrace All

    The Parts We do everything in Strict Mode Sunday, October 7, 12
  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
  5. Why are there Rules? Sunday, October 7, 12

  6. Rules help us to do it right But who decides

    what is right? Sunday, October 7, 12
  7. Right as it applies to Soup Sunday, October 7, 12

  8. What is authentic minestrone soup? Oh!! Google Images will know..

    Sunday, October 7, 12
  9. Sunday, October 7, 12

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

  11. Correctness is Subjective Sunday, October 7, 12

  12. Each of us is unique. Each of us considers something

    harmful. Sunday, October 7, 12
  13. Sunday, October 7, 12

  14. Harmful is Subjective Sunday, October 7, 12

  15. Germaine de Staël (1766 - 1817) “Rules are only barriers

    to prevent children from falling” Sunday, October 7, 12
  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
  17. Wikipedia Policy (2001) “If a rule prevents you from improving

    or maintaining Wikipedia, ignore it.” Sunday, October 7, 12
  18. How to Break the Rules... Sunday, October 7, 12

  19. The with statement Sunday, October 7, 12

  20. Why are you not meant to use it? 1) accidental

    clobbering and implicit global creation. Sunday, October 7, 12
  21. var dragger = { increment: 1, direction: 'vertical', activationDrag: 2,

    onRelease: cleanUp } with(dragger) { interval = 2; direction = 'any'; } window.interval; //2 Sunday, October 7, 12
  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
  23. Why are you not meant to use it? 2) cost

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

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

    Sunday, October 7, 12
  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
  27. Why is it useful? 2) it replicates block scope. Sunday,

    October 7, 12
  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
  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
  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
  31. The eval statement Sunday, October 7, 12

  32. Why are you not meant to use it? 1) code

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

    closure optimization Sunday, October 7, 12
  34. Why are you not meant to use it? 3) cost

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

    Sunday, October 7, 12
  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
  37. // From JSON2.org if (/^[\],:{}\s]*$/ .test(text.replace(/*regEx*/, '@') .replace(/*regEx*/, ']') .replace(/*regEx*/,

    ''))) { j = eval('(' + text + ')'); } Sunday, October 7, 12
  38. Why is it useful? 2) It’s how your console rolls

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

    7, 12
  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
  41. The Function constructor Sunday, October 7, 12

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

    7, 12
  43. It evaluates code in a direct lexical child of the

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

    in a predictable scope. Sunday, October 7, 12
  45. Why is it useful? 2) Only globals are exposed to

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

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

    12
  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
  49. Where is it used? 2) Underscore.js string interpolation Sunday, October

    7, 12
  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
  51. The == operator Sunday, October 7, 12

  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
  53. Why is it useful? 1) coerces operands to the same

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

    7, 12
  55. //this... if ((x === null) || (x === undefined)) //...is

    logically identical to this if (x == null) Sunday, October 7, 12
  56. Why is it useful? 3) when it’s bloody obvious Sunday,

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

    Sunday, October 7, 12
  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
  59. The Array constructor Sunday, October 7, 12

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

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

  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
  63. If you enjoyed breaking these rules you might consider breaking

    these ones too... Sunday, October 7, 12
  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
  65. It’s OK to break a Rule if... Sunday, October 7,

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

    12
  67. You can mitigate (or safely ignore) the concerns of the

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

  69. Kristine Kathryn Rusch “Become an expert at the rules. Then

    break them with creativity and style” Sunday, October 7, 12
  70. tl;dr Be Good. And if you can’t be good, Be

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