exports.extendNative = function() { Object.keys(ArrayExt).forEach(function(k) { if (Array.prototype[k]) return; // don't overwrite existing members Array.prototype[k] = function() { var fn = ArrayExt[k] , args = [].slice.call(arguments) ; args.shift(this); fn.apply(ArrayExt, args); }; }); }; var ArrayToString = [].toString(); var ArrayExt = exports.ArrayExt = { // abbrev // [1,2,3,4,5].at(-1) => 5 at: function(a, i) { if (i >= 0) return a[i]; return a[a.length + i]; } // TODO make this work for non-array objects , compact: function(a) { var b = [] , i = a.length ; while (i--) { if (a[i] !== null && a[i] !== undefined) b[i] = a[i]; } return b; } , first: function(a) { return a[0]; } // Based on underscore.js's flatten , flatten: function(a) { return a.reduce(function(initial, elem) { if (elem && elem.flatten) initial = initial.concat(elem.flatten()); else initial.push(elem); return initial; }); } , grep: function(a, regex) { return a.filter(function(v) { return regex.match(v); }); } , last: function(a) { return a[a.length-1]; } , max: function(a) { return a.reduce(function(max, v) { return v > max ? v : max }); } , min: function(a) { return a.reduce(function(min, v) { return v < min ? v : min }); } // pack // partition , toString: function(a) { return '[' + ArrayToString.call(a) + ']'; } , unique: function(a) { var b = [] , i = 0 , n = a.length ; for (; i < n; ++i) { if (b.indexOf(a[i]) === -1) b.push(a[i]); } return b; } };