Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
Created January 29, 2012 21:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gordonbrander/1700841 to your computer and use it in GitHub Desktop.
Save gordonbrander/1700841 to your computer and use it in GitHub Desktop.
jQuery-style Instantiation: Decorate a Constructor Function to Enforce `new` and `return this`
// Takes a function and wraps it, making sure:
//
// * It enforces `new`
// * It returns `this`
//
// Doing this enables a jQuery coding style for object creation,
// where constructor functions become chain-able immediately after
// construction, and don't have to be called with `new`. For example:
//
// var F = decorateCtor(function (a, b, c) { ... });
// F.prototype.rock = 'on';
// F(1, 2, 3).rock;
// >> 'on'
var decorateCtor = (function () {
// Fast lookups.
var bind = Function.prototype.bind,
slice = Array.prototype.slice;
return function (callback) {
// Return a new function -- the "decoration" wrapper function.
return function Ctor () {
if (!(this instanceof Ctor)) {
// Capture the arguments in array format.
var args = slice.call(arguments);
// Add `null` to the beginning.. this is our "context"
// for bind -- i.e. no context, since calling new overrides
// bound contexts but not bound arguments.
// See <http://dmitrysoshnikov.com/notes/note-1-ecmascript-bound-functions/#constructor-with-various-number-of-arguments>
args.unshift(null);
// Bind the arguments (in array format) to the constructor,
// creating a new bound function.
var boundCtor = bind.apply(Ctor, args);
// Initialize the constructor with bound arguments.
return new boundCtor();
}
callback.apply(this, arguments);
return this;
};
};
})();
@gordonbrander
Copy link
Author

If you use this in older browsers, you'll also want to include a shim for Function.prototype.bind (don't worry, it's pretty small).

Some background on the technique:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment