Permalink
Browse files

add a bunch of helpful comments

this is pretty dense code after all
  • Loading branch information...
1 parent 13c34a8 commit bfb9ac2bfff262bd7020ebfaf2c47a0c1d3bdb7d @jneen committed Jan 5, 2012
Showing with 38 additions and 0 deletions.
  1. +38 −0 src/p.js
View
@@ -1,4 +1,5 @@
var P = (function(slice, prototype, hasOwnProperty, undefined) {
+ // helper functions that also help minification
function isObject(o) { return typeof o === 'object'; }
function isFunction(f) { return typeof f === 'function'; }
@@ -9,28 +10,61 @@ var P = (function(slice, prototype, hasOwnProperty, undefined) {
_superclass = Object;
}
+ // C is the class to be returned.
+ // There are three ways C will be called:
+ //
+ // 1) We call `new C` to create a new uninitialized object.
+ // The behavior is similar to Object.create, where the prototype
+ // relationship is set up, but the ::init method is not run.
+ // Note that in this case we have `this instanceof C`, so we don't
+ // spring the first trap. Also, `args` is undefined, so the initializer
+ // doesn't get run.
+ //
+ // 2) A user will simply call C(a, b, c, ...) to create a new object with
+ // initialization. This allows the user to create objects without `new`,
+ // and in particular to initialize objects with variable arguments, which
+ // is impossible with tne `new` keyword. Note that in this case,
+ // !(this instanceof C) springs the return trap at the beginning, and
+ // C is called with the `new` keyword and one argument, which is the
+ // Arguments object passed in.
+ //
+ // 3) For internal use only, if new C(args) is called, where args is an
+ // Arguments object. In this case, the presence of `new` means the
+ // return trap is not sprung, but the initializer is called if present.
+ //
+ // TODO: the Chrome inspector shows all created objects as `C` rather than `Object`.
+ // Setting the .name property seems to have no effect. Is there a way to override
+ // this behavior?
function C(args) {
var self = this;
if (!(self instanceof C)) return new C(arguments);
if (args && isFunction(self.init)) self.init.apply(self, args);
}
+ // set up the prototype of the new class
+ // note that this resolves to `new Object`
+ // if the superclass isn't given
C[prototype] = new _superclass;
var proto = C[prototype]
, _super = _superclass[prototype]
, extensions = {}
;
+ // set the constructor property, for convenience
proto.constructor = C;
if (isFunction(definition)) {
+ // call the defining function with all the arguments you need
+ // extensions captures the return value.
extensions = definition.call(C, proto, _super, C, _superclass);
}
else if (isObject(definition)) {
+ // if you passed an object instead, we'll take it
extensions = definition;
}
+ // ...and extend it
if (isObject(extensions)) {
for (var ext in extensions) {
if (hasOwnProperty.call(extensions, ext)) {
@@ -42,5 +76,9 @@ var P = (function(slice, prototype, hasOwnProperty, undefined) {
return C;
}
+ // ship it
return P;
+
+ // as a minifier optimization, we've closured in a few helper functions
+ // and the string 'prototype' (C[p] is much shorter than C.prototype)
})([].slice, 'prototype', ({}).hasOwnProperty);

0 comments on commit bfb9ac2

Please sign in to comment.