Compare to [underscorejs][1] if it pleases you. Once again, I hope this is well commented. Please let me know what comments/improvements I can add. Please review all aspects of this code. /*************************************************************************************************** **UTILITY - additional coverage for looping, type checking, extending ... - consistent ordering, naming conventions ... - fewer function branches - increased type checking and modularity - vector based unit testing ***************************************************************************************************/ // self used to hold client or server side global ( window or exports ) (function (self, undef) { "use strict"; // holds (P)ublic properties var $P = {}, // holds p(R)ivate properties $R = {}, // native methods (alphabetical order) nativeFilter = Array.prototype.filter, nativeIsArray = Array.isArray, nativeSlice = Array.prototype.slice, nativeSome = Array.prototype.some, nativeToString = Object.prototype.toString; $P.noConflict = (function () { // $R.g holds the single global variable, used to hold all packages // methods $R.g = '$A'; $R.previous = self[$R.g]; // utility is required by all other packages // start the "pack"age list $P.pack = { utility: true }; return function () { var temp = self[$R.g]; self[$R.g] = $R.previous; return temp; }; }()); $P.isType = function (type, obj) { return $P.getType(obj) === type; }; // returns type in a captialized string form // typeof is only accurate for function, string, number, boolean, and // undefined. null and array are both incorrectly reported as object $P.getType = function (obj) { return nativeToString.call(obj).slice(8, -1); }; $P.isFalse = function (obj) { return obj === false; }; $P.isUndefined = function (obj) { return obj === undef; }; $P.isNull = function (obj) { return obj === null; }; $P.isNumber = function (value) { return (typeof value === 'number') && isFinite(value); }; // detects null or undefined $P.isGone = function (obj) { return obj == null; }; // detects anything but null or undefined $P.isHere = function (obj) { return obj != null; }; // detects null, undefined, NaN, ('' ""), 0, -0, false $P.isFalsy = function (obj) { return !obj; }; // detects any thing but null, undefined, NaN, ('' ""), 0, -0, false $P.isTruthy = function (obj) { return !!obj; }; // shortcut as their are only two primitive boolean values // detects a "boxed" boolean as well $P.isBoolean = function (obj) { return obj === true || obj === false || nativeToString.call(obj) === '[object Boolean]'; }; // delegates to native $P.isArray = nativeIsArray || function (obj) { return nativeToString.call(obj) === '[object Array]'; }; // jslint prefers {}.constructor(obj) over Object(obj) $P.isObjectAbstract = function (obj) { // return obj === Object(obj); return !!(obj && (obj === {}.constructor(obj))); }; // has a numeric length property $P.isArrayAbstract = function (obj) { return !!(obj && obj.length === +obj.length); }; $P.someIndex = function (arr, func, con) { var ind, len; // prevent type errors, note function is validated if ((arr == null) || (arr.length !== +arr.length) || (typeof func !== 'function')) { return; } // delegate to native some() if (nativeSome && arr.some === nativeSome) { return arr.some(func, con); } // if the function passes back a truthy value, the loop will terminate for (ind = 0, len = arr.length; ind < len; ind++) { if (func.call(con, arr[ind], ind, arr)) { return true; } } return false; }; $P.someKey = function (obj, func, con) { var key; // prevent type errors // for-in will filter out null and undefined if ((obj == null) || (typeof func !== 'function')) { return; } for (key in obj) { if (obj.hasOwnProperty(key)) { // if the function passes back a truthy value, // the loop will terminate if (func.call(con, obj[key], key, obj)) { return true; } } } return false; }; // loop through space separated "tokens" in a string $P.eachString = function (str, func, con) { // prevent type errors if (typeof str !== 'string' || str === "" || typeof func !== 'function') { return; } $P.someIndex(str.split(/\s+/), func, con); }; // does not extend through the prototype chain // implemented for objects only $P.extend = function (obj) { // loop througth elements beyond obj $P.someIndex(nativeSlice.call(arguments, 1), function (val) { // extend it $P.someKey(val, function (val_inner, key) { obj[key] = val_inner; }); }); return obj; }; // extends non-prototype properties from obj2 on to obj1 $P.extendSafe = function (obj1, obj2) { var key; for (key in obj2) { if (obj2.hasOwnProperty(key)) { if (obj1.hasOwnProperty(key)) { throw "naming collision: " + key; } obj1[key] = obj2[key]; } } return obj1; }; // if incorrect types are passed, it will return an empty array // arrays only $P.filter = function (arr, func, con) { var results = []; if ((arr == null) || (typeof func !== 'function')) { return results; } if (nativeFilter && arr.filter === nativeFilter) { return arr.filter(func, con); } $P.someIndex(arr, function (val, ind, arr) { if (func.call(con, val, ind, arr)) { results.push(val); } }); return results; }; $P.clone = function (obj) { return $P.extend({}, obj); }; $P.someIndex(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Object'], function (val) { $P['is' + val] = function (obj) { return $P.isType(val, obj); }; }); $P.addU = function (str, suf) { return str + '_' + suf; }; $P.removeU = function (str) { if (typeof str !== 'string' || str === "") { return false; } return str.slice(str, str.lastIndexOf("_")); }; $P.removeSuffix = function (str, len) { if (typeof str !== 'string' || str === "") { return false; } return str.slice(0, -len); }; // equivalent to IIFE but "nicer" syntax $P.runTest = (function () { var tests = {}; return function (name, arr, func) { tests[name] = func.apply(this, arr); }; }()); self[$R.g] = $P.extendSafe($P, {}); // this will hold the global object - window or exports }(this)); **`someIndex()` and `someKey()` compared to underscore `each()`** So the way I chose to write `someIndex()` and `someKey()` was organically or as a process. I wanted to abstract the looping idioms I got tired of writing into methods. Because `for` and `for-in` can be broke out of I decided that `some()` was a better building block then `each()` from my perspective. After, I did this I compared what I had to underscore. My design choices were different in other ways as well. -- Please note, if you need speed just use a for or for-in loop, if you need clean concise code, use the abstraction -- The other way I diverged from underscore is that I wrote some separately for arrays and objects, because when I code I always know which one I am looping through, hence I wanted to express this knowledge in my code - someIndex() and someKey(). Another way I diverged was that I type check all the inputs in one line, for some reason underscore chooses not to type check the callback function. The other way I diverged is I don't check for any internal breaks, that are internal use only, in underscore this is shown as an equality check for `breaker`. Also, as in all my code b.c. JS is not block scoped yet, I put my var definitions up top. That's the gist of it, please let me know if I can elaborate more. Below is the code for both: $P.someIndex = function (arr, func, con) { var ind, len; // prevent type errors, note function is validated if ((arr == null) || (arr.length !== +arr.length) || (typeof func !== 'function')) { return; } // delegate to native some() if (nativeSome && arr.some === nativeSome) { return arr.some(func, con); } // if the function passes back a truthy value, the loop will terminate for (ind = 0, len = arr.length; ind < len; ind++) { if (func.call(con, arr[ind], ind, arr)) { return true; } } return false; }; var each = _.each = _.forEach = function(obj, iterator, context) { if (obj == null) return; if (nativeForEach && obj.forEach === nativeForEach) { obj.forEach(iterator, context); } else if (obj.length === +obj.length) { for (var i = 0, length = obj.length; i < length; i++) { if (iterator.call(context, obj[i], i, obj) === breaker) return; } } else { var keys = _.keys(obj); for (var i = 0, length = keys.length; i < length; i++) { if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; } } }; [1]:http://underscorejs.org/