var prototypeMethods = require('./proto_prototype');
var objectMethods = require('./proto_object');
Functions that Array implements natively are also added - they can be used with array-like objects and for chaining (native functions are always called).
var arrayMethods = require('./proto_array');
var functionMethods = require('./proto_function');
var stringMethods = require('./proto_string');
var numberMethods = require('./proto_number');
var utilMethods = require('./proto_util');
Option name | Type | Description |
---|---|---|
self | Any | A value to be wrapped |
return | Proto |
_
can be used to create a wrapped value (object, function, array, etc.) to allow chaining of Proto functions.
To unwrap, _
method of a wrapped value should be used.
Usage:
var arr = _({ 0: 3, 1: 4, 2: 5, length: 3})
.toArray()
.prependArray([1, 2])
.appendArray([6, 7, 8])
._();
A wrapped object is an instance of _
(Proto
class).
Chaining is implemented for development convenience, but it has performance overhead, not only to wrap and unwrap values but in each function call.
Although all Proto functions are implemented as methods operating on this and the overhead to redefine them as functions is very small, the overhead to redefine them as methods of wrapped value is slightly higher - chaining is 15-25% slower than using functions (properties of _ that take the first parameter).
In cases when performance is critical, you may want to avoid using chaining.
function Proto(self) {
// wrap passed parameter in _ object
var wrapped = Object.create(Proto.prototype);
wrapped.self = self;
return wrapped;
};
var _ = Proto;
// store raw methods from different modules in __ object (double "_")
var __ = {};
objectMethods.extend.call(__, objectMethods);
__.extend.call(__, prototypeMethods);
__.extend.call(__, arrayMethods);
__.extend.call(__, stringMethods);
__.extend.call(__, numberMethods);
__.extend.call(__, functionMethods);
__.extend.call(__, utilMethods);
// add __ as property of Proto, so they can be used as mixins in other classes
__.defineProperty(Proto, '__', __);
// add _ method to unwrap wrapped value (Proto instance)
function unwrapProto() { return this.self; }
__.extendProto.call(Proto, { _: unwrapProto });
// add constants (functions will be overwritten)
__.extend.call(Proto, objectMethods._constants);
// add functions that take first parameter instead of "this" to Proto
var protoFuncs = __.mapKeys.call(__, utils.makeProtoFunction, true);
__.extend.call(Proto, protoFuncs);
// add Proto wrapped value instance methods to Proto prototype
var protoInstanceMethods = __.mapKeys.call(__, utils.makeProtoInstanceMethod, true);
__.extendProto.call(Proto, protoInstanceMethods);
In windows environment, a global _
value is preserved in _.underscore
if (typeof window == 'object') {
// preserve existing _ object
if (window._)
Proto.underscore = window._
// expose global _ and Proto
window._ = Proto;
}
if (typeof module == 'object' && module.exports)
// export for node/browserify
module.exports = Proto;