-
-
Save jfhbrook/1350330 to your computer and use it in GitHub Desktop.
| var util = require("util"); | |
| // Am I the only one that finds this more readable? | |
| // (Trailing super, return constructor) | |
| var inherits = function (inherits, fn) { | |
| util.inherits(fn, inherits); | |
| return fn; | |
| } |
| josh@onix:/tmp/inherits$ node | |
| > var inherits = require("./inherits"); | |
| > var EE = require("events").EventEmitter; | |
| > | |
| > var FooBar = inherits(EE, function () { | |
| ... this.on("foo", function () { | |
| ... console.log("bar"); | |
| ... }); | |
| ... }); | |
| > | |
| > var foobar = new FooBar; | |
| > | |
| > foobar.emit("foo"); | |
| bar | |
| true | |
| > | |
| var util = require("util"); | |
| // This slightly beefier version can also apply your arguments through the | |
| // whole shebang, but this might be better left to do by-hand. | |
| // Alternately, one could use a flag to make auto-application "switch-able". | |
| var Inherits = function (Inheritance, Constructor) { | |
| var Inherited = function () { | |
| Inheritance.apply(this, arguments); | |
| Constructor.apply(this, arguments); | |
| } | |
| util.inherits(Inherited, Inheritance); | |
| return Inherited; | |
| } |
| // Supposing I wanted to make a "really nice" util.inherits... | |
| function inherits (ctor, superCtor) { | |
| ctor.super_ = superCtor; | |
| // Do this.super_.call(this, arg2, arg2) yo'self. | |
| // Alias prototype to proto_ for less typing | |
| ctor.proto_ = ctor.prototype = Object.create(superCtor.prototype, { | |
| constructor: { | |
| value: ctor, | |
| enumerable: false, | |
| writable: true, | |
| configurable: true | |
| } | |
| }); | |
| // Return the constructor | |
| return ctor; | |
| } |
What we have already ... is powerful enough to do even fairly sophisticated OOP voodoo.
Yeah, definitely. I wouldn't expect any sugar to do much more than a ctor-returning util.inherits. I'm personally not big on inheritance; Usually I just push objects around between functions. I also worry that adding too much sugar can obfuscate what you're really trying to do. That said, I feel like it could use some help in the readability department. To each his own, I guess.
Returning the ctor is annoying. You lose function hoisting, which is nice.
Is it? Like I said, I tend not to exploit hoisting. On the other hand, the fact that this changes this behavior does mean that returning the ctor isn't backwards-compatible; That is, this change would break code like Jason's. (Edit: Unless I misunderstand what you're saying. This seems like a weird behavior to me, even for javascript.)
it's very rare that you need to pass the same exact arguments to the superclass constructor
I think this is a matter of style. What if your constructors all take just an options hash? I was just reading code that does this, three levels of util.inherits deep. I agree, though, that it's less general. In retrospect, I would also -1 adding passing the arguments but could go either way on returning the ctor.
Plus, it's not like I can't just write my own utils, with blackjack and hookers.
and even more rare that you have an indeterminate number of arguments to a constructor
Well, yeah, but I don't know what that number of arguments is going to be a'priori so I'd have to do it that way for n arguments.
The jury is still out. I'll try it for a few months.
I might have to start doing that myself.
absolutely! I think the trailing inline function is much more readable (and returning the constructor), it's how i've designed the jay library type functions. I've also got two options, one where you specify the constructor directly, and one where you define the prototype object which can optionally contain a new subconstructor. you can check it out at http://github.com/ngspinners/jay
I think it does not work with
var MyEmitter = function () { ... }. Even if it did work, I would personally avoid it on aesthetic or confusion grounds.I agree about hoisting sparingly. I only use if the function definition immediately follows the reference. But I am now experimenting with using this to make EventEmitter code more clear.
The jury is still out. I'll try it for a few months. Thoughts.
on_enddoesn't count, think of something meaningful.)Real-world example: https://github.com/iriscouch/probe_couchdb/blob/master/couch.js#L103-120. I didn't go crazy, just small, simple callbacks.