Reviewing this version
Which browsers are targeted?
Would you consider making an AMD or UMD module instead of exporting to the global?
- L131. I feel you may get into random trouble if people use event names like
valueOf
, etc. UseObject.create(null)
or a string-map lib - L157.
typeof arguments[0] === 'object'
:null
passes this test. You want ````Object(arguments[0]) === arguments[0]``` - L167-177 when you iterate over an array, use
.forEach
or one of its friends. In this case, I think you want.reduce
(problem repeated in different places in the code) - L205-206. Too much work :-p
_handlers = Object.create(null)
(recreate an empty object instead of cleaning it. It costs a bit more GC but... one object per _unbind call...) - L261. This is tricky. The call may throw an error. You don't catch it, so one handler throwing prevents all other handlers from being called. It's unlikemy to be the expected behavior (add a comment if it's on purpose, though). Two possible solutions: try/catch and ignore the error or schedule each handler in its own setTimeout 0.
- L602. I wonder if a job shouldn't be an object with a kill/cancel method instead of the global killJob method.
- L620. It sounds like a lot of work to remove the job. Is the data structure right? Maybe killJob is called rarely enough that it doesn't matter?
- L738.
_isRunning
is an internal variable. You're in charge of making sure it remains a boolean, you shouldn't need to!!
. TypeScript can help ;-) - L893 - 949. I'm willing to bet Lodash has functions for this and does it better than you ever will. Just import the parts you need from Lodash
- L956 __dateNow: have you considered using performance.now?
- L30: I believe the semilcolon isn't that important
- No need for the
undefined
in argument. It can't be overriden. That's an urban legend (or maybe true in super-old IEs?). If someone overides it, it can only be you by using the variable name, shadowing the global one. Just don't use this variable name ;-) - I'm not sure the coding convention is necessary in the sense that if you export at the end, it's clear what's exported and consequently what isn't.
.call(this)
for an IIFE works, but the global object is then refered asthis
which is not an obvious way to reference it. I prefer:
(function(global){
if(global.conrad){...}
})(this)
I feel global.conrad
reads better than this.conrad
- L148. _bind:
events
is of type string, string[] should work too... or I don't know. Sometimes later, it's expected that it can be an object. Anyway, the doc doesn't match the code. - L154. _bind: the use of
this
is awkward. what does it reference? (I guess the exported conrad reference, but I feel _bind would be better inlined or something)` - L163.
Object.prototype.toString.call(events) === '[object Array]'
this isArray.isArray
. Use it and polyfill if necessary. (happens in different places)
Questions
About the comments part:
Your points are definitely relevant. Some remarks:
this
reference in the cosmetics part) comes from a custom event dispatcher I use in lot of projects, where_handlers
is actuallythis._handlers
and I do not want to get leaked (for instance in domino.js). But you're definitely right here.About the cosmetics part:
I will just trust you on these, since you've clearly seen more code that I have.
global
way of writing this is clearly more readable.This was all very interesting, and will give a new version soon - and some patches in domino.js, the new sigma.js draft, etc... And thanks a lot. I've never seen a so precise and well organized code review, I'm impressed :)