Everything is Permitted: Extending Built-ins
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Everything is Permitted: Extending Built-ins

  • 5,551 views
Uploaded on

Adding methods to built-in objects: it’s one of JavaScript’s most powerful features. It’s also a great way to offend the sensibilities of your colleagues. We all hear that it’s irresponsible, that......

Adding methods to built-in objects: it’s one of JavaScript’s most powerful features. It’s also a great way to offend the sensibilities of your colleagues. We all hear that it’s irresponsible, that it’s sloppy, that it’s flat-out bad practice and should be avoided.

I’m tired of this one-sided battle. In this talk, I’m going to push back against whatever blog post you read that told you that extending built-ins was unconditionally and universally bad. I’m gonna go all Howard Beale on your asses.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
5,551
On Slideshare
5,340
From Embeds
211
Number of Embeds
6

Actions

Shares
Downloads
38
Comments
0
Likes
4

Embeds 211

http://lanyrd.com 197
https://twitter.com 4
http://www.techgig.com 3
http://translate.googleusercontent.com 3
http://us-w1.rockmelt.com 2
http://twitter.com 2

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Everything is Permitted: Extending Built-ins Andrew Dupont http://andrewdupont.net
  • 2. Remy Sharp (flickr.com/photos/remysharp)
  • 3. “ There’s a whole lot of know-nothing advocacy that’s still happening in the JS/webdev/design world these days, and it annoys me to no end. I’m not sure how our community got so religious and fact-disoriented, but it has got to stop.”Alex Russell
  • 4. “If you use this book as a guide, by all means leave the road when you wish. That is precisely the use of a road: to reach individually chosen points of departure. By all means break the rules, and break them beautifully, deliberately and well. That is one of the ends for which they exist.”Robert Bringhurst,The Elements of Typographic Style
  • 5. “Break any of these rules sooner than say anything outright barbarous.”George Orwell,“Politics and the English Language”
  • 6. “Commandments”are no way to write code.
  • 7. Alex (flickr.com/photos/littlebirdfeet/)
  • 8. @DonaldGlover Donald GloverFuck what you heard, SHORTS AREDOPE. Just wear them right. Not mid leglike you’re at a fuckin Creed concert.30 Jul via Echofon
  • 9. Code has social customs.
  • 10. IN THE BEGINNING (ca. 2005)
  • 11. Prototype 1.1
  • 12. Object.prototype.extend = function(object) { for (var property in object) { this[property] = object[property]; } return this;};
  • 13. var whiteHouse = { washington: adams };whiteHouse.extend({ adams: jefferson });for (var president in whiteHouse) console.log(president);//=> washington, adams, extend
  • 14. Object.prototype is verbotenhttp://erik.eae.net/archives/2005/06/06/22.13.54/
  • 15. You can do anything you want, assuming it’s all your code
  • 16. Object.prototype.extend became Object.extend
  • 17. if (!Array.prototype.push) { Array.prototype.push = function() { var startLength = this.length; for (var i = 0; i < arguments.length; i++) this[startLength + i] = arguments[i]; return this.length; };}
  • 18. Prototype 1.4 introduced Enumerable
  • 19. for...in loops on arrays are usually dumb
  • 20. JavaScript “Associative Arrays” Considered Harmful http://is.gd/js_considered_harmful
  • 21. Prototype 1.5 introduced “Extended” elements
  • 22. // Prototype 1.4Element.addClassName(some_element, active);Element.show();$(some_element).setAttribute(title, Active item);// Prototype 1.5$(some_element).addClassName(active).show(). setAttribute(title, Active item);
  • 23. This was slow in IE
  • 24. @kangax kangaxAlso `typeofdocument.querySelectorAll(*).item` is string in IE8. Well, thatsjust silly.16 Dec 08 via web
  • 25. What’s wrong with extending the DOMhttp://perfectionkills.com/whats-wrong-with-extending-the-dom/
  • 26. Maintainable JavaScript: Don’t modify objects you don’t own http://is.gd/zakas_maintainable_javascript
  • 27. Who owns built-ins?
  • 28. We all do.
  • 29. Social customs are a proven way to manage shared property.
  • 30. Case in point: RUBY
  • 31. Ruby and JavaScriptare Smalltalk-influenced
  • 32. Rails gave RubyActive Support
  • 33. ActiveSupport::CoreExtensions::Numeric 1.day.ago #=> Thu Apr 21 01:57:24 -0500 2011 (4.years + 12.days).from_now #=> Mon May 04 01:58:30 -0500 2015 7.5.megabytes #=> 7864320.0
  • 34. Symbol#to_procresult = names.map {|name| name.upcase }# becomes...result = names.map(&:upcase)
  • 35. http://brockman.se/2004/method-references/
  • 36. Prototype 1.4Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); };};
  • 37. EcmaScript 5.1 Specification
  • 38. Obviously,there were fights along the way
  • 39. “I only re-open a class after I’ve tried every other option like subclassing, wrapping, etc. If nothing else works or is too much effort for the modification, then I document the hell out of my modification and try desperately to localize the change so that it doesnt hurt anyone else.”Zed Shaw,“The Chainsaw Infanticide Logger Manuever”http://is.gd/chainsaw_infanticide
  • 40. “Dont slip a concrete dildo into someones box of Fruit Loops. They wont be happy with your Morning Breakfast Surprise. Put the concrete dildo in a clearly labeled box, with instructions. Then when someone encounters a problem (‘Hey, something is screwing me here. Maybe its the concrete dildo?’) at least they know to ask.”The Higgs Bozohttp://is.gd/concrete_dildo
  • 41. “In my mind, in Ruby < 2.0, there’s a category of library which is ‘provide a number of useful core extensions.’ The three major ones are ActiveSupport, Extlib and Facets. In general, applications need to choose one, but not more of these libraries to avoid conflicts.”Yehuda Katzhttp://is.gd/cQar9O
  • 42. Lessons learned by Rubyists:
  • 43. Make it obvious when you’re defining core extensions. module SomeLibrary module CoreExtensions module Object def foo # ... end end end end class Object include SomeLibrary::CoreExtensions::Object end
  • 44. Make core extensions as atomic as possible.require active_support/core_ext/numeric/bytes3.megabytes#=> 31457283.days.ago# NoMethodError: undefined method `days for 3:Fixnum
  • 45. If you must monkey-patch, do so seamlessly. Don’t break the old method’s contract. class Array alias_method :foo_original :foo def foo(arg) puts "Adding advice to the foo method" foo_original(arg) end end
  • 46. Unsolved problems:
  • 47. Only one library gets the privilege to extend built-ins.
  • 48. Libraries I require will o en decide for themselves which core extensions will be used.{}.blank?# NoMethodError: undefined method `blank? for {}:Hashrequire rails{}.blank?#=> true
  • 49. Can we extend built-ins safely right now?
  • 50. Object.prototype.extend = function(object) { for (var property in object) { this[property] = object[property]; } return this;};
  • 51. Object.prototype.extend = function(object) { for (var property in object) { this[property] = object[property]; } return this;};
  • 52. ES5 to the rescue?Object.defineProperty(Object.prototype, extend, { writable: true, configurable: true, enumerable: false, value: function() { for (var i = 0, len = arguments.length, source; i < len; i++) { source = arguments[i]; for (var property in source) { if (source.hasOwnProperty(property)) this[property] = source[property]; } } } });
  • 53. var whiteHouse = { washington: adams };whiteHouse.extend({ adams: jefferson });for (var president in whiteHouse) console.log(president);//=> washington, adams
  • 54. But wait…var whiteHouse = { extend: adams };whiteHouse.extend({ adams: jefferson });// TypeError: Property extend of object #<Object>// is not a function
  • 55. And also…console.log(extend);//=> [Function]
  • 56. Object.prototype is still verboten
  • 57. If you extend other built-ins,consider turning off enumerability.
  • 58. What about Node?
  • 59. node-timehttps://github.com/TooTallNate/node-time
  • 60. var time = require(time);var date = new Date();date.setTimeZone(America/Chicago);console.log(date.toString());console.log(date.getTimezone());console.log(date.getTimezoneAbbr());Output:Tue Apr 26 2011 02:45:21 GMT-0500 (CDT)America/ChicagoCDT
  • 61. What about the browser?
  • 62. We’ll be needing ES5 polyfills“A polyfill … is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively.” Remy Sharp http://remysharp.com/2010/10/08/what-is-a-polyfill/
  • 63. if (!Object.keys) { Object.keys = function(object) { if (object !== Object(object)) throw new TypeError(Object.keys called on non-object); var results = []; for (var property in object) { if (object.hasOwnProperty(property)) results.push(property); } return results; };}
  • 64. if (!Function.prototype.bind) { Function.prototype.bind = function(object) { var slice = Array.prototype.slice, args = slice.call(arguments, 1), self = this; var nop = function() {}; var bound = function() { return self.apply( this instanceof nop ? this : (object || {}), args.concat(slice.call(arguments)) ); }; nop.prototype = self.prototype; bound.prototype = new nop(); return bound; };}
  • 65. Let’s start with bind.
  • 66. Prototype 1.7.1 will have spec compliancefor all methods defined by ES5.
  • 67. Will we be able toextend built-ins safely someday?
  • 68. The future:CLASSBOXES
  • 69. “[W]e present classboxes, a module system for object- oriented languages that allows method addition and replacement. Moreover, the changes made by a classbox are only visible to that classbox (or classboxes that import it), a feature we call local rebinding.”So ware Composition Group,University of Bernhttp://scg.unibe.ch/research/classboxes
  • 70. A classbox-like system called “refinements” has been proposed for Ruby 2.0. module TimeExtensions refine Numeric do def minutes; self * 60; end end end 2.minutes #=> NoMethodError using TimeExtensions 2.minutes #=> 120
  • 71. Could we have classboxes in JavaScript?
  • 72. Strawman: Scoped Object Extensionsmodule NumericExtensions { export extension Time = Number.prototype { days: function() {}, /* ... */ ago: function() {}, fromNow: function() {} }}function setExpiringCookie(key, value) { import NumericExtensions.Time; var expires = (3).days().fromNow(); setCookie(key, value, expires);}(3).days().fromNow();//=> TypeError: Object 3 has no method days
  • 73. SOMEDAY
  • 74. Questions?