Skip to main content
edited tags; edited title
Link
Malachi
  • 28.7k
  • 11
  • 86
  • 188

A Utility package for basic utility functionscomparable to underscores.js

Rollback to Revision 5
Source Link
Jamal
  • 34.9k
  • 13
  • 133
  • 237

Compare to underscorejs 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.

/***************************************************************************************************
**ARC


Goal:
 - to create a small efficient package system that can be extended.
 
How it works:

 The utility package is independent.
 The comms package requires the utility package.
 The dom package requires the utility package.
 The frame package requires the utility and comms package.
 The boot package requires the utility, dom and comms package.
 
 Notes
 - passes jslint
   - browser:   allow access to the DOM
   - forin:     allow for in with out prototype filtering
   - plusplus:  alow ++
   - eqeq:      allow == and !=
 - minifies with closure
 - is broken up into packages with listed dependencies
   - utility, dom, comms, frame, boot
 - uses a single global variable with safe extending for each package
 
 
***************************************************************************************************/

/***************************************************************************************************
**UTILITY

Goal

 - the smallest most efficient utility library
 
List of Functions

 - Type Checking
   isType, getType, isUndefined, isNumber, isGone, isHere, isFalse, isTruthy, isBoolean, isArray,
   isObjectAbstract, isArrayAbstract, 
 - Looping
   someIndex, someKey, someString, 
 - Extending 
   extend, extendSafe
 - General
   filter, clone
 
Advantages
 
 - additional coverage for utilities,
   consistent ordering, naming conventions, input validation, fewer function branches
 
`someIndex` and `someKey` explained:

`someIndex` and `someKey` are abstractions for looping through arrays and objects respectively.  
Unlike underscore, where you can use `some` or `each` to loop through both arrays andtype objectschecking, 
I chose to only use `some` and break its usage up between array literals and objectextending literals.  This 
is b.c. when I code I always know which I 
 am- dealingconsistent withordering, and I wanted to express this knowledge 
innaming myconventions code.  This allowed my to write two shorter functions with less dependencies.  
I use `someIndex` and `someKey` for all loops, whether breaks are needed or not.  
This confuses some underscore users because they think it is in-efficient, 
they might be unaware that even the underscorefewer `each`function branches
contains a check for an internal break.  Also I wanted to emulate the raw loops- asincreased muchtype as
possible,checking and you can of course break out of a for or for-in loop whenever you like.modularity
In short, if you want to go faster, use raw `for` or `for-in` loops in eithervector case.based unit 
 testing
***************************************************************************************************/

/*jslint
  browser:    true,
  forin:      true,
  plusplus:   true,
  eqeq:       true,
*/

// 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 capitalizedcaptialized 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);
    };

    // primarily for callbacks
    $P.isFalse = function (obj) {
        return obj === false;
    };

    // primarily for callbacks
    $P.isTrueisUndefined = function (obj) {
        return obj === true;undef;
    };

    // primarily for callbacks
    $P.isNull = function (obj) {
        return obj === null;
    };

    // for older browsers which do no protect undefined
    $P.isUndefined = function (obj) {
        return obj === undef;
    };
    
    // not complete
    $P.isNumber = function (objvalue) {
        return (typeof objvalue === '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.someStringeachString = 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);
        };
    });

    // equivalent to IIFE but "nicer" syntax
    $P.runTest = (function () {
        var tests = {};
        return function (name, arr, func) {
            tests[name] = func.apply(this, arr);
        };
    }());

    // ignore from here down, in the process of removal
    $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.

Also, regarding elegance, I feel my code is more elegant, as the type checking is consistent and consolidated, my var declarations are more naturally inline with how the interpreter reads them, and comments, white space, and a 4 space indent level make the code easier to read.

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;
      }
    }
  };
    
    
/***************************************************************************************************
**ARC


Goal:
 - to create a small efficient package system that can be extended.
 
How it works:

 The utility package is independent.
 The comms package requires the utility package.
 The dom package requires the utility package.
 The frame package requires the utility and comms package.
 The boot package requires the utility, dom and comms package.
 
 Notes
 - passes jslint
   - browser:   allow access to the DOM
   - forin:     allow for in with out prototype filtering
   - plusplus:  alow ++
   - eqeq:      allow == and !=
 - minifies with closure
 - is broken up into packages with listed dependencies
   - utility, dom, comms, frame, boot
 - uses a single global variable with safe extending for each package
 
 
***************************************************************************************************/

/***************************************************************************************************
**UTILITY

Goal

 - the smallest most efficient utility library
 
List of Functions

 - Type Checking
   isType, getType, isUndefined, isNumber, isGone, isHere, isFalse, isTruthy, isBoolean, isArray,
   isObjectAbstract, isArrayAbstract, 
 - Looping
   someIndex, someKey, someString, 
 - Extending 
   extend, extendSafe
 - General
   filter, clone
 
Advantages
 
 - additional coverage for utilities,
   consistent ordering, naming conventions, input validation, fewer function branches
 
`someIndex` and `someKey` explained:

`someIndex` and `someKey` are abstractions for looping through arrays and objects respectively.  
Unlike underscore, where you can use `some` or `each` to loop through both arrays and objects, 
I chose to only use `some` and break its usage up between array literals and object literals.  This 
is b.c. when I code I always know which I am dealing with, and I wanted to express this knowledge 
in my code.  This allowed my to write two shorter functions with less dependencies.  
I use `someIndex` and `someKey` for all loops, whether breaks are needed or not.  
This confuses some underscore users because they think it is in-efficient, 
they might be unaware that even the underscore `each` 
contains a check for an internal break.  Also I wanted to emulate the raw loops as much as
possible, and you can of course break out of a for or for-in loop whenever you like.
In short, if you want to go faster, use raw `for` or `for-in` loops in either case.  
 
***************************************************************************************************/

/*jslint
  browser:    true,
  forin:      true,
  plusplus:   true,
  eqeq:       true,
*/

// self used to hold client or server side global
(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
        $R.g = '$A';
        $R.previous = self[$R.g];

        // utility is required by all other packages
        $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 capitalized 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);
    };

    // primarily for callbacks
    $P.isFalse = function (obj) {
        return obj === false;
    };

    // primarily for callbacks
    $P.isTrue = function (obj) {
        return obj === true;
    };

    // primarily for callbacks
    $P.isNull = function (obj) {
        return obj === null;
    };

    // for older browsers which do no protect undefined
    $P.isUndefined = function (obj) {
        return obj === undef;
    };
    
    // not complete
    $P.isNumber = function (obj) {
        return (typeof obj === 'number');
    };

    // 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]';
    };

    $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)));
    };

    $P.isArrayAbstract = function (obj) {
        return !!(obj && obj.length === +obj.length);
    };

    $P.someIndex = function (arr, func, con) {
        var ind,
            len;

        // prevent type errors
        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
        if ((obj == null) || (typeof func !== 'function')) {
            return;
        }
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (func.call(con, obj[key], key, obj)) {
                    return true;
                }
            }
        }
        return false;
    };

    // loop through space separated "tokens" in a string
    $P.someString = 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);
        };
    });

    // equivalent to IIFE but "nicer" syntax
    $P.runTest = (function () {
        var tests = {};
        return function (name, arr, func) {
            tests[name] = func.apply(this, arr);
        };
    }());

    // ignore from here down, in the process of removal
    $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);
    };
    self[$R.g] = $P.extendSafe($P, {});
}(this));

Compare to underscorejs 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.

Also, regarding elegance, I feel my code is more elegant, as the type checking is consistent and consolidated, my var declarations are more naturally inline with how the interpreter reads them, and comments, white space, and a 4 space indent level make the code easier to read.

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;
      }
    }
  };
    
    
added 379 characters in body
Source Link
anon
anon

Compare to underscore if it pleases you. Once again, I hope this is well commented. Please let me know what comments/improvements I can add.

/***************************************************************************************************
**ARC
 

Goal:
 - to create a small efficient package system that can be extended.
 
How it works:
 
 The utility package is independent.
 The comms package requires the utility package.
 The dom package requires the utility package.
 The frame package requires the utility and comms package.
 The boot package requires the utility, dom and comms package.
 
 Notes
 - passes jslint
   - browser:   allow access to the DOM
   - forin:     allow for in with out prototype filtering
   - plusplus:  alow ++
   - eqeq:      allow == and !=
 - minifies with closure
 - is broken up into packages with listed dependencies
   - utility, dom, comms, frame, boot
 - uses a single global variable with safe extending for each package
 
 
***************************************************************************************************/

/***************************************************************************************************
**UTILITY

Goal

 - the smallest most efficient utility library
 
List of Functions

 - Type Checking
   isType, getType, isUndefined, isNumber, isGone, isHere, isFalse, isTruthy, isBoolean, isArray,
   isObjectAbstract, isArrayAbstract, 
 - Looping
   someIndex, someKey, someString, 
 - Extending 
   extend, extendSafe
 - General
   filter, clone
 
Advantages
 
 - additional coverage for utilities, removal of pointless functions - isNull() for example, 
   consistent ordering, naming conventions, input validation, fewer function branches
 
`someIndex` and `someKey` explained:

`someIndex` and `someKey` are abstractions for looping through arrays and objects respectively.  
Unlike underscore, where you can use `some` or `each` to loop through both arrays and objects, 
I chose to only use `some` and break its usage up between array literals and object literals.  This 
is b.c. when I code I always know which I am dealing with, and I wanted to express this knowledge 
in my code.  This allowed my to write two shorter functions with less dependencies.  
I use `someIndex` and `someKey` for all loops, whether breaks are needed or not.  
This confuses some underscore users because they think it is in-efficient, 
they might be unaware that even the underscore `each` 
contains a check for an internal break.  Also I wanted to emulate the raw loops as much as
possible, and you can of course break out of a for or for-in loop whenever you like.
In short, if you want to go faster, use raw `for` or `for-in` loops in either case.  

***************************************************************************************************/

/*jslint
  browser:    true,
  forin:      true,
  plusplus:   true,
  eqeq:       true,
*/

// self used to hold client or server side global
(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
        $R.g = '$A';
        $R.previous = self[$R.g];

        // utility is required by all other packages
        $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 capitalized 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);
    };

    // primarily for callbacks
    $P.isFalse = function (obj) {
        return obj === false;
    };

    // primarily for callbacks
    $P.isTrue = function (obj) {
        return obj === true;
    };

    // primarily for callbacks
    $P.isNull = function (obj) {
        return obj === null;
    };

    // for older browsers which do no protect undefined
    $P.isUndefined = function (obj) {
        return obj === undef;
    };
    
    // not complete
    $P.isNumber = function (valueobj) {
        return (typeof valueobj === 'number');
    };

    // 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]';
    };

    $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)));
    };

    $P.isArrayAbstract = function (obj) {
        return !!(obj && obj.length === +obj.length);
    };

    $P.someIndex = function (arr, func, con) {
        var ind,
            len;

        // prevent type errors
        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
        if ((obj == null) || (typeof func !== 'function')) {
            return;
        }
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (func.call(con, obj[key], key, obj)) {
                    return true;
                }
            }
        }
        return false;
    };

    // loop through space separated "tokens" in a string
    $P.someString = 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);
        };
    });

    // equivalent to IIFE but "nicer" syntax
    $P.runTest = (function () {
        var tests = {};
        return function (name, arr, func) {
            tests[name] = func.apply(this, arr);
        };
    }());

    // ignore from here down, in the process of removal
    $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);
    };
    self[$R.g] = $P.extendSafe($P, {});
}(this));

Compare to underscore if it pleases you. Once again, I hope this is well commented. Please let me know what comments/improvements I can add.

/***************************************************************************************************
**ARC

Goal:
 - to create a small efficient package system that can be extended.
 
How it works:
 The utility package is independent.
 The comms package requires the utility package.
 The dom package requires the utility package.
 The frame package requires the utility and comms package.
 The boot package requires the utility, dom and comms package.
 
 Notes
 - passes jslint
   - browser:   allow access to the DOM
   - forin:     allow for in with out prototype filtering
   - plusplus:  alow ++
   - eqeq:      allow == and !=
 - minifies with closure
 - is broken up into packages with listed dependencies
   - utility, dom, comms, frame, boot
 - uses a single global variable with safe extending for each package
 
 
***************************************************************************************************/

/***************************************************************************************************
**UTILITY

Goal

 - the smallest most efficient utility library
 
List of Functions

 - Type Checking
   isType, getType, isUndefined, isNumber, isGone, isHere, isFalse, isTruthy, isBoolean, isArray,
   isObjectAbstract, isArrayAbstract, 
 - Looping
   someIndex, someKey, someString, 
 - Extending 
   extend, extendSafe
 - General
   filter, clone
 
Advantages
 
 - additional coverage for utilities, removal of pointless functions - isNull() for example, 
   consistent ordering, naming conventions, input validation, fewer function branches
 
`someIndex` and `someKey` explained:

`someIndex` and `someKey` are abstractions for looping through arrays and objects respectively.  
Unlike underscore, where you can use `some` or `each` to loop through both arrays and objects, 
I chose to only use `some` and break its usage up between array literals and object literals.  This 
is b.c. when I code I always know which I am dealing with, and I wanted to express this knowledge 
in my code.  This allowed my to write two shorter functions with less dependencies.  
I use `someIndex` and `someKey` for all loops, whether breaks are needed or not.  
This confuses some underscore users because they think it is in-efficient, 
they might be unaware that even the underscore `each` 
contains a check for an internal break.  Also I wanted to emulate the raw loops as much as
possible, and you can of course break out of a for or for-in loop whenever you like.
In short, if you want to go faster, use raw `for` or `for-in` loops in either case.  

***************************************************************************************************/

// self used to hold client or server side global
(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
        $R.g = '$A';
        $R.previous = self[$R.g];

        // utility is required by all other packages
        $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 capitalized 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.isUndefined = function (obj) {
        return obj === undef;
    };

    // not complete
    $P.isNumber = function (value) {
        return (typeof value === 'number');
    };

    // 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]';
    };

    $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)));
    };

    $P.isArrayAbstract = function (obj) {
        return !!(obj && obj.length === +obj.length);
    };

    $P.someIndex = function (arr, func, con) {
        var ind,
            len;

        // prevent type errors
        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
        if ((obj == null) || (typeof func !== 'function')) {
            return;
        }
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (func.call(con, obj[key], key, obj)) {
                    return true;
                }
            }
        }
        return false;
    };

    // loop through space separated "tokens" in a string
    $P.someString = 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);
        };
    });

    // equivalent to IIFE but "nicer" syntax
    $P.runTest = (function () {
        var tests = {};
        return function (name, arr, func) {
            tests[name] = func.apply(this, arr);
        };
    }());

    // ignore from here down, in the process of removal
    $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);
    };
    self[$R.g] = $P.extendSafe($P, {});
}(this));
/***************************************************************************************************
**ARC
 

Goal:
 - to create a small efficient package system that can be extended.
 
How it works:
 
 The utility package is independent.
 The comms package requires the utility package.
 The dom package requires the utility package.
 The frame package requires the utility and comms package.
 The boot package requires the utility, dom and comms package.
 
 Notes
 - passes jslint
   - browser:   allow access to the DOM
   - forin:     allow for in with out prototype filtering
   - plusplus:  alow ++
   - eqeq:      allow == and !=
 - minifies with closure
 - is broken up into packages with listed dependencies
   - utility, dom, comms, frame, boot
 - uses a single global variable with safe extending for each package
 
 
***************************************************************************************************/

/***************************************************************************************************
**UTILITY

Goal

 - the smallest most efficient utility library
 
List of Functions

 - Type Checking
   isType, getType, isUndefined, isNumber, isGone, isHere, isFalse, isTruthy, isBoolean, isArray,
   isObjectAbstract, isArrayAbstract, 
 - Looping
   someIndex, someKey, someString, 
 - Extending 
   extend, extendSafe
 - General
   filter, clone
 
Advantages
 
 - additional coverage for utilities,
   consistent ordering, naming conventions, input validation, fewer function branches
 
`someIndex` and `someKey` explained:

`someIndex` and `someKey` are abstractions for looping through arrays and objects respectively.  
Unlike underscore, where you can use `some` or `each` to loop through both arrays and objects, 
I chose to only use `some` and break its usage up between array literals and object literals.  This 
is b.c. when I code I always know which I am dealing with, and I wanted to express this knowledge 
in my code.  This allowed my to write two shorter functions with less dependencies.  
I use `someIndex` and `someKey` for all loops, whether breaks are needed or not.  
This confuses some underscore users because they think it is in-efficient, 
they might be unaware that even the underscore `each` 
contains a check for an internal break.  Also I wanted to emulate the raw loops as much as
possible, and you can of course break out of a for or for-in loop whenever you like.
In short, if you want to go faster, use raw `for` or `for-in` loops in either case.  

***************************************************************************************************/

/*jslint
  browser:    true,
  forin:      true,
  plusplus:   true,
  eqeq:       true,
*/

// self used to hold client or server side global
(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
        $R.g = '$A';
        $R.previous = self[$R.g];

        // utility is required by all other packages
        $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 capitalized 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);
    };

    // primarily for callbacks
    $P.isFalse = function (obj) {
        return obj === false;
    };

    // primarily for callbacks
    $P.isTrue = function (obj) {
        return obj === true;
    };

    // primarily for callbacks
    $P.isNull = function (obj) {
        return obj === null;
    };

    // for older browsers which do no protect undefined
    $P.isUndefined = function (obj) {
        return obj === undef;
    };
    
    // not complete
    $P.isNumber = function (obj) {
        return (typeof obj === 'number');
    };

    // 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]';
    };

    $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)));
    };

    $P.isArrayAbstract = function (obj) {
        return !!(obj && obj.length === +obj.length);
    };

    $P.someIndex = function (arr, func, con) {
        var ind,
            len;

        // prevent type errors
        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
        if ((obj == null) || (typeof func !== 'function')) {
            return;
        }
        for (key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (func.call(con, obj[key], key, obj)) {
                    return true;
                }
            }
        }
        return false;
    };

    // loop through space separated "tokens" in a string
    $P.someString = 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);
        };
    });

    // equivalent to IIFE but "nicer" syntax
    $P.runTest = (function () {
        var tests = {};
        return function (name, arr, func) {
            tests[name] = func.apply(this, arr);
        };
    }());

    // ignore from here down, in the process of removal
    $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);
    };
    self[$R.g] = $P.extendSafe($P, {});
}(this));
deleted 619 characters in body
Source Link
anon
anon
Loading
deleted 619 characters in body
Source Link
anon
anon
Loading
deleted 3137 characters in body
Source Link
anon
anon
Loading
added 283 characters in body
Source Link
anon
anon
Loading
added 2751 characters in body
Source Link
anon
anon
Loading
deleted 1887 characters in body
Source Link
anon
anon
Loading
added 32 characters in body
Source Link
konijn
  • 33.8k
  • 5
  • 69
  • 264
Loading
Source Link
anon
anon
Loading