underscore.js | |
|---|---|
| (function() { |
Baseline setup | |
| Establish the root object, | var root = this; |
| Save the previous value of the | var previousUnderscore = root._; |
| Establish the object that gets returned to break out of a loop iteration. | var breaker = {}; |
| Save bytes in the minified (but not gzipped) version: | var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; |
| Create quick reference variables for speed access to core prototypes. | var slice = ArrayProto.slice,
- unshift = ArrayProto.unshift,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty; |
| All ECMAScript 5 native function implementations that we hope to use -are declared here. | var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind; |
| Create a safe reference to the Underscore object for use below. | var _ = function(obj) { return new wrapper(obj); }; |
| Export the Underscore object for Node.js, with
-backwards-compatibility for the old | if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root['_'] = _;
- } |
| Current version. | _.VERSION = '1.3.3'; |
Collection Functions | |
| The cornerstone, an | 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, l = obj.length; i < l; i++) {
- if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (_.has(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- }; |
| Return the results of applying the iterator to each element.
-Delegates to ECMAScript 5's native | _.map = _.collect = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- if (obj.length === +obj.length) results.length = obj.length;
- return results;
- }; |
| Reduce builds up a single result from a list of values, aka | _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError('Reduce of empty array with no initial value');
- return memo;
- }; |
| The right-associative version of reduce, also known as | _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var reversed = _.toArray(obj).reverse();
- if (context && !initial) iterator = _.bind(iterator, context);
- return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
- }; |
| Return the first value which passes a truth test. Aliased as | _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- }; |
| Return all the elements that pass a truth test.
-Delegates to ECMAScript 5's native | _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- }; |
| Return all the elements for which a truth test fails. | _.reject = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- each(obj, function(value, index, list) {
- if (!iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- }; |
| Determine whether all of the elements match a truth test.
-Delegates to ECMAScript 5's native | _.every = _.all = function(obj, iterator, context) {
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- }; |
| Determine if at least one element in the object matches a truth test.
-Delegates to ECMAScript 5's native | var any = _.some = _.any = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- }; |
| Determine if a given value is included in the array or object using | _.include = _.contains = function(obj, target) {
- var found = false;
- if (obj == null) return found;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- found = any(obj, function(value) {
- return value === target;
- });
- return found;
- }; |
| Invoke a method (with arguments) on every item in a collection. | _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- return _.map(obj, function(value) {
- return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
- });
- }; |
| Convenience version of a common use case of | _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- }; |
| Return the maximum element or (element-based computation). | _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.max.apply(Math, obj);
- if (!iterator && _.isEmpty(obj)) return -Infinity;
- var result = {computed : -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- }; |
| Return the minimum element (or element-based computation). | _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0]) return Math.min.apply(Math, obj);
- if (!iterator && _.isEmpty(obj)) return Infinity;
- var result = {computed : Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- }; |
| Shuffle an array. | _.shuffle = function(obj) {
- var shuffled = [], rand;
- each(obj, function(value, index, list) {
- rand = Math.floor(Math.random() * (index + 1));
- shuffled[index] = shuffled[rand];
- shuffled[rand] = value;
- });
- return shuffled;
- }; |
| Sort the object's values by a criterion produced by an iterator. | _.sortBy = function(obj, val, context) {
- var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- if (a === void 0) return 1;
- if (b === void 0) return -1;
- return a < b ? -1 : a > b ? 1 : 0;
- }), 'value');
- }; |
| Groups the object's values by a criterion. Pass either a string attribute -to group by, or a function that returns the criterion. | _.groupBy = function(obj, val) {
- var result = {};
- var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
- each(obj, function(value, index) {
- var key = iterator(value, index);
- (result[key] || (result[key] = [])).push(value);
- });
- return result;
- }; |
| Use a comparator function to figure out at what index an object should -be inserted so as to maintain order. Uses binary search. | _.sortedIndex = function(array, obj, iterator) {
- iterator || (iterator = _.identity);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >> 1;
- iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
- }
- return low;
- }; |
| Safely convert anything iterable into a real, live array. | _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (_.isArguments(obj)) return slice.call(obj);
- if (obj.toArray && _.isFunction(obj.toArray)) return obj.toArray();
- return _.values(obj);
- }; |
| Return the number of elements in an object. | _.size = function(obj) {
- return _.isArray(obj) ? obj.length : _.keys(obj).length;
- }; |
Array Functions | |
| Get the first element of an array. Passing n will return the first N
-values in the array. Aliased as | _.first = _.head = _.take = function(array, n, guard) {
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- }; |
| Returns everything but the last entry of the array. Especcialy useful on
-the arguments object. Passing n will return all the values in
-the array, excluding the last N. The guard check allows it to work with
- | _.initial = function(array, n, guard) {
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
- }; |
| Get the last element of an array. Passing n will return the last N
-values in the array. The guard check allows it to work with | _.last = function(array, n, guard) {
- if ((n != null) && !guard) {
- return slice.call(array, Math.max(array.length - n, 0));
- } else {
- return array[array.length - 1];
- }
- }; |
| Returns everything but the first entry of the array. Aliased as | _.rest = _.tail = function(array, index, guard) {
- return slice.call(array, (index == null) || guard ? 1 : index);
- }; |
| Trim out all falsy values from an array. | _.compact = function(array) {
- return _.filter(array, function(value){ return !!value; });
- }; |
| Return a completely flattened version of an array. | _.flatten = function(array, shallow) {
- return _.reduce(array, function(memo, value) {
- if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
- memo[memo.length] = value;
- return memo;
- }, []);
- }; |
| Return a version of the array that does not contain the specified value(s). | _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- }; |
| Produce a duplicate-free version of the array. If the array has already
-been sorted, you have the option of using a faster algorithm.
-Aliased as | _.uniq = _.unique = function(array, isSorted, iterator) {
- var initial = iterator ? _.map(array, iterator) : array;
- var results = []; |
| The | if (array.length < 3) isSorted = true;
- _.reduce(initial, function (memo, value, index) {
- if (isSorted ? _.last(memo) !== value || !memo.length : !_.include(memo, value)) {
- memo.push(value);
- results.push(array[index]);
- }
- return memo;
- }, []);
- return results;
- }; |
| Produce an array that contains the union: each distinct element from all of -the passed-in arrays. | _.union = function() {
- return _.uniq(_.flatten(arguments, true));
- }; |
| Produce an array that contains every item shared between all the -passed-in arrays. (Aliased as "intersect" for back-compat.) | _.intersection = _.intersect = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- }; |
| Take the difference between one array and a number of other arrays. -Only the elements present in just the first array will remain. | _.difference = function(array) {
- var rest = _.flatten(slice.call(arguments, 1), true);
- return _.filter(array, function(value){ return !_.include(rest, value); });
- }; |
| Zip together multiple lists into a single array -- elements that share -an index go together. | _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
- return results;
- }; |
| If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
-we need this function. Return the position of the first occurrence of an
-item in an array, or -1 if the item is not included in the array.
-Delegates to ECMAScript 5's native | _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i, l;
- if (isSorted) {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
- for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
- return -1;
- }; |
| Delegates to ECMAScript 5's native | _.lastIndexOf = function(array, item) {
- if (array == null) return -1;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
- var i = array.length;
- while (i--) if (i in array && array[i] === item) return i;
- return -1;
- }; |
| Generate an integer Array containing an arithmetic progression. A port of
-the native Python | _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
-
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
-
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
-
- return range;
- }; |
Function (ahem) Functions | |
| Reusable constructor function for prototype setting. | var ctor = function(){}; |
| Create a function bound to a given object (assigning | _.bind = function bind(func, context) {
- var bound, args;
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- if (!_.isFunction(func)) throw new TypeError;
- args = slice.call(arguments, 2);
- return bound = function() {
- if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
- ctor.prototype = func.prototype;
- var self = new ctor;
- var result = func.apply(self, args.concat(slice.call(arguments)));
- if (Object(result) === result) return result;
- return self;
- };
- }; |
| Bind all of an object's methods to that object. Useful for ensuring that -all callbacks defined on an object belong to it. | _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length == 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- }; |
| Memoize an expensive function by storing its results. | _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- }; |
| Delays a function for the given number of milliseconds, and then calls -it with the arguments supplied. | _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
- }; |
| Defers a function, scheduling it to run after the current call stack has -cleared. | _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- }; |
| Returns a function, that, when invoked, will only be triggered at most once -during a given window of time. | _.throttle = function(func, wait) {
- var context, args, timeout, throttling, more, result;
- var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
- return function() {
- context = this; args = arguments;
- var later = function() {
- timeout = null;
- if (more) func.apply(context, args);
- whenDone();
- };
- if (!timeout) timeout = setTimeout(later, wait);
- if (throttling) {
- more = true;
- } else {
- result = func.apply(context, args);
- }
- whenDone();
- throttling = true;
- return result;
- };
- }; |
| Returns a function, that, as long as it continues to be invoked, will not
-be triggered. The function will be called after it stops being called for
-N milliseconds. If | _.debounce = function(func, wait, immediate) {
- var timeout;
- return function() {
- var context = this, args = arguments;
- var later = function() {
- timeout = null;
- if (!immediate) func.apply(context, args);
- };
- if (immediate && !timeout) func.apply(context, args);
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- };
- }; |
| Returns a function that will be executed at most one time, no matter how -often you call it. Useful for lazy initialization. | _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- return memo = func.apply(this, arguments);
- };
- }; |
| Returns the first function passed as an argument to the second, -allowing you to adjust arguments, run code before and after, and -conditionally execute the original function. | _.wrap = function(func, wrapper) {
- return function() {
- var args = [func].concat(slice.call(arguments, 0));
- return wrapper.apply(this, args);
- };
- }; |
| Returns a function that is the composition of a list of functions, each -consuming the return value of the function that follows. | _.compose = function() {
- var funcs = arguments;
- return function() {
- var args = arguments;
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- }; |
| Returns a function that will only be executed after being called N times. | _.after = function(times, func) {
- if (times <= 0) return func();
- return function() {
- if (--times < 1) { return func.apply(this, arguments); }
- };
- }; |
Object Functions | |
| Retrieve the names of an object's properties.
-Delegates to ECMAScript 5's native | _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
- return keys;
- }; |
| Retrieve the values of an object's properties. | _.values = function(obj) {
- return _.map(obj, _.identity);
- }; |
| Return a sorted list of the function names available on the object.
-Aliased as | _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- }; |
| Extend a given object with all the properties in passed-in object(s). | _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- obj[prop] = source[prop];
- }
- });
- return obj;
- }; |
| Return a copy of the object only containing the whitelisted properties. | _.pick = function(obj) {
- var result = {};
- each(_.flatten(slice.call(arguments, 1)), function(key) {
- if (key in obj) result[key] = obj[key];
- });
- return result;
- }; |
| Fill in a given object with default properties. | _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- });
- return obj;
- }; |
| Create a (shallow-cloned) duplicate of an object. | _.clone = function(obj) {
- if (!_.isObject(obj)) return obj;
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- }; |
| Invokes interceptor with the obj, and then returns obj. -The primary purpose of this method is to "tap into" a method chain, in -order to perform operations on intermediate results within the chain. | _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- }; |
| Internal recursive comparison function. | function eq(a, b, stack) { |
| Identical objects are equal. | if (a === b) return a !== 0 || 1 / a == 1 / b; |
| A strict comparison is necessary because | if (a == null || b == null) return a === b; |
| Unwrap any wrapped objects. | if (a._chain) a = a._wrapped;
- if (b._chain) b = b._wrapped; |
| Invoke a custom | if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
- if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a); |
| Compare | var className = toString.call(a);
- if (className != toString.call(b)) return false;
- switch (className) { |
| Strings, numbers, dates, and booleans are compared by value. | case '[object String]': |
| Primitives and their corresponding object wrappers are equivalent; thus, | return a == String(b);
- case '[object Number]': |
|
| return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
- case '[object Date]':
- case '[object Boolean]': |
| Coerce dates and booleans to numeric primitive values. Dates are compared by their
-millisecond representations. Note that invalid dates with millisecond representations
-of | return +a == +b; |
| RegExps are compared by their source patterns and flags. | case '[object RegExp]':
- return a.source == b.source &&
- a.global == b.global &&
- a.multiline == b.multiline &&
- a.ignoreCase == b.ignoreCase;
- }
- if (typeof a != 'object' || typeof b != 'object') return false; |
| Assume equality for cyclic structures. The algorithm for detecting cyclic
-structures is adapted from ES 5.1 section 15.12.3, abstract operation | var length = stack.length;
- while (length--) { |
| Linear search. Performance is inversely proportional to the number of -unique nested structures. | if (stack[length] == a) return true;
- } |
| Add the first object to the stack of traversed objects. | stack.push(a);
- var size = 0, result = true; |
| Recursively compare objects and arrays. | if (className == '[object Array]') { |
| Compare array lengths to determine if a deep comparison is necessary. | size = a.length;
- result = size == b.length;
- if (result) { |
| Deep compare the contents, ignoring non-numeric properties. | while (size--) { |
| Ensure commutative equality for sparse arrays. | if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
- }
- }
- } else { |
| Objects with different constructors are not equivalent. | if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false; |
| Deep compare objects. | for (var key in a) {
- if (_.has(a, key)) { |
| Count the expected number of properties. | size++; |
| Deep compare each member. | if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
- }
- } |
| Ensure that both objects contain the same number of properties. | if (result) {
- for (key in b) {
- if (_.has(b, key) && !(size--)) break;
- }
- result = !size;
- }
- } |
| Remove the first object from the stack of traversed objects. | stack.pop();
- return result;
- } |
| Perform a deep comparison to check if two objects are equal. | _.isEqual = function(a, b) {
- return eq(a, b, []);
- }; |
| Is a given array, string, or object empty? -An "empty" object has no enumerable own-properties. | _.isEmpty = function(obj) {
- if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (_.has(obj, key)) return false;
- return true;
- }; |
| Is a given value a DOM element? | _.isElement = function(obj) {
- return !!(obj && obj.nodeType == 1);
- }; |
| Is a given value an array? -Delegates to ECMA5's native Array.isArray | _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) == '[object Array]';
- }; |
| Is a given variable an object? | _.isObject = function(obj) {
- return obj === Object(obj);
- }; |
| Is a given variable an arguments object? | _.isArguments = function(obj) {
- return toString.call(obj) == '[object Arguments]';
- };
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return !!(obj && _.has(obj, 'callee'));
- };
- } |
| Is a given value a function? | _.isFunction = function(obj) {
- return toString.call(obj) == '[object Function]';
- }; |
| Is a given value a string? | _.isString = function(obj) {
- return toString.call(obj) == '[object String]';
- }; |
| Is a given value a number? | _.isNumber = function(obj) {
- return toString.call(obj) == '[object Number]';
- }; |
| Is a given object a finite number? | _.isFinite = function(obj) {
- return _.isNumber(obj) && isFinite(obj);
- }; |
| Is the given value | _.isNaN = function(obj) { |
|
| return obj !== obj;
- }; |
| Is a given value a boolean? | _.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
- }; |
| Is a given value a date? | _.isDate = function(obj) {
- return toString.call(obj) == '[object Date]';
- }; |
| Is the given value a regular expression? | _.isRegExp = function(obj) {
- return toString.call(obj) == '[object RegExp]';
- }; |
| Is a given value equal to null? | _.isNull = function(obj) {
- return obj === null;
- }; |
| Is a given variable undefined? | _.isUndefined = function(obj) {
- return obj === void 0;
- }; |
| Has own property? | _.has = function(obj, key) {
- return hasOwnProperty.call(obj, key);
- }; |
Utility Functions | |
| Run Underscore.js in noConflict mode, returning the | _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- }; |
| Keep the identity function around for default iterators. | _.identity = function(value) {
- return value;
- }; |
| Run a function n times. | _.times = function (n, iterator, context) {
- for (var i = 0; i < n; i++) iterator.call(context, i);
- }; |
| Escape a string for HTML interpolation. | _.escape = function(string) {
- return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
- }; |
| If the value of the named property is a function then invoke it; -otherwise, return it. | _.result = function(object, property) {
- if (object == null) return null;
- var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- }; |
| Add your own custom functions to the Underscore object, ensuring that -they're correctly added to the OOP wrapper as well. | _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- addToWrapper(name, _[name] = obj[name]);
- });
- }; |
| Generate a unique integer id (unique within the entire client session). -Useful for temporary DOM ids. | var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = idCounter++;
- return prefix ? prefix + id : id;
- }; |
| By default, Underscore uses ERB-style template delimiters, change the -following template settings to use alternative delimiters. | _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g,
- escape : /<%-([\s\S]+?)%>/g
- }; |
| When customizing | var noMatch = /.^/; |
| Certain characters need to be escaped so that they can be put into a -string literal. | var escapes = {
- '\\': '\\',
- "'": "'",
- 'r': '\r',
- 'n': '\n',
- 't': '\t',
- 'u2028': '\u2028',
- 'u2029': '\u2029'
- };
-
- for (var p in escapes) escapes[escapes[p]] = p;
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
- var unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g; |
| Within an interpolation, evaluation, or escaping, remove HTML escaping -that had been previously added. | var unescape = function(code) {
- return code.replace(unescaper, function(match, escape) {
- return escapes[escape];
- });
- }; |
| JavaScript micro-templating, similar to John Resig's implementation. -Underscore templating handles arbitrary delimiters, preserves whitespace, -and correctly escapes quotes within interpolated code. | _.template = function(text, data, settings) {
- settings = _.defaults(settings || {}, _.templateSettings); |
| Compile the template source, taking care to escape characters that -cannot be included in a string literal and then unescape them in code -blocks. | var source = "__p+='" + text
- .replace(escaper, function(match) {
- return '\\' + escapes[match];
- })
- .replace(settings.escape || noMatch, function(match, code) {
- return "'+\n_.escape(" + unescape(code) + ")+\n'";
- })
- .replace(settings.interpolate || noMatch, function(match, code) {
- return "'+\n(" + unescape(code) + ")+\n'";
- })
- .replace(settings.evaluate || noMatch, function(match, code) {
- return "';\n" + unescape(code) + "\n;__p+='";
- }) + "';\n"; |
| If a variable is not specified, place data values in local scope. | if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
- source = "var __p='';" +
- "var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n" +
- source + "return __p;\n";
-
- var render = new Function(settings.variable || 'obj', '_', source);
- if (data) return render(data, _);
- var template = function(data) {
- return render.call(this, data, _);
- }; |
| Provide the compiled function source as a convenience for build time -precompilation. | template.source = 'function(' + (settings.variable || 'obj') + '){\n' +
- source + '}';
-
- return template;
- }; |
| Add a "chain" function, which will delegate to the wrapper. | _.chain = function(obj) {
- return _(obj).chain();
- }; |
The OOP Wrapper | |
| If Underscore is called as a function, it returns a wrapped object that -can be used OO-style. This wrapper holds altered versions of all the -underscore functions. Wrapped objects may be chained. | var wrapper = function(obj) { this._wrapped = obj; }; |
| Expose | _.prototype = wrapper.prototype; |
| Helper function to continue chaining intermediate results. | var result = function(obj, chain) {
- return chain ? _(obj).chain() : obj;
- }; |
| A method to easily add functions to the OOP wrapper. | var addToWrapper = function(name, func) {
- wrapper.prototype[name] = function() {
- var args = slice.call(arguments);
- unshift.call(args, this._wrapped);
- return result(func.apply(_, args), this._chain);
- };
- }; |
| Add all of the Underscore functions to the wrapper object. | _.mixin(_); |
| Add all mutator Array functions to the wrapper. | each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- var wrapped = this._wrapped;
- method.apply(wrapped, arguments);
- var length = wrapped.length;
- if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
- return result(wrapped, this._chain);
- };
- }); |
| Add all accessor Array functions to the wrapper. | each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- wrapper.prototype[name] = function() {
- return result(method.apply(this._wrapped, arguments), this._chain);
- };
- }); |
| Start chaining a wrapped Underscore object. | wrapper.prototype.chain = function() {
- this._chain = true;
- return this;
- }; |
| Extracts the result from a wrapped and chained object. | wrapper.prototype.value = function() {
- return this._wrapped;
- };
-
-}).call(this);
-
- |
-
-
- Underscore is a - utility-belt library for JavaScript that provides a lot of the - functional programming support that you would expect in - Prototype.js - (or Ruby), - but without extending any of the built-in JavaScript objects. It's the - tie to go along with jQuery's tux, - and Backbone.js's suspenders. -
- -- Underscore provides 60-odd functions that support both the usual - functional suspects: map, select, invoke — - as well as more specialized helpers: function binding, javascript - templating, deep equality testing, and so on. It delegates to built-in - functions, if present, so modern browsers will use the - native implementations of forEach, map, reduce, - filter, every, some and indexOf. -
- -- A complete Test & Benchmark Suite - is included for your perusal. -
- -- You may also read through the annotated source code. -
- -- The project is - hosted on GitHub. - You can report bugs and discuss features on the - issues page, - on Freenode in the #documentcloud channel, - or send tweets to @documentcloud. -
- -- Underscore is an open-source component of DocumentCloud. -
- -| Development Version (1.3.3) | -37kb, Uncompressed with Plentiful Comments | -
| Production Version (1.3.3) | -4kb, Minified and Gzipped | -
- each_.each(list, iterator, [context])
- Alias: forEach
-
- Iterates over a list of elements, yielding each in turn to an iterator
- function. The iterator is bound to the context object, if one is
- passed. Each invocation of iterator is called with three arguments:
- (element, index, list). If list is a JavaScript object, iterator's
- arguments will be (value, key, list). Delegates to the native
- forEach function if it exists.
-
-_.each([1, 2, 3], function(num){ alert(num); });
-=> alerts each number in turn...
-_.each({one : 1, two : 2, three : 3}, function(num, key){ alert(num); });
-=> alerts each number in turn...
-
-
- map_.map(list, iterator, [context])
- Alias: collect
-
- Produces a new array of values by mapping each value in list
- through a transformation function (iterator). If the native map method
- exists, it will be used instead. If list is a JavaScript object,
- iterator's arguments will be (value, key, list).
-
-_.map([1, 2, 3], function(num){ return num * 3; });
-=> [3, 6, 9]
-_.map({one : 1, two : 2, three : 3}, function(num, key){ return num * 3; });
-=> [3, 6, 9]
-
-
- reduce_.reduce(list, iterator, memo, [context])
- Aliases: inject, foldl
-
- Also known as inject and foldl, reduce boils down a
- list of values into a single value. Memo is the initial state
- of the reduction, and each successive step of it should be returned by
- iterator.
-
-var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0);
-=> 6
-
-
-
- reduceRight_.reduceRight(list, iterator, memo, [context])
- Alias: foldr
-
- The right-associative version of reduce. Delegates to the
- JavaScript 1.8 version of reduceRight, if it exists. Foldr
- is not as useful in JavaScript as it would be in a language with lazy
- evaluation.
-
-var list = [[0, 1], [2, 3], [4, 5]];
-var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
-=> [4, 5, 2, 3, 0, 1]
-
-
-
- find_.find(list, iterator, [context])
- Alias: detect
-
- Looks through each value in the list, returning the first one that
- passes a truth test (iterator). The function returns as
- soon as it finds an acceptable element, and doesn't traverse the
- entire list.
-
-var even = _.find([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
-=> 2
-
-
-
- filter_.filter(list, iterator, [context])
- Alias: select
-
- Looks through each value in the list, returning an array of all
- the values that pass a truth test (iterator). Delegates to the
- native filter method, if it exists.
-
-var evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
-=> [2, 4, 6]
-
-
-
- reject_.reject(list, iterator, [context])
-
- Returns the values in list without the elements that the truth
- test (iterator) passes. The opposite of filter.
-
-var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
-=> [1, 3, 5]
-
-
-
- all_.all(list, iterator, [context])
- Alias: every
-
- Returns true if all of the values in the list pass the iterator
- truth test. Delegates to the native method every, if present.
-
-_.all([true, 1, null, 'yes'], _.identity); -=> false -- -
- any_.any(list, [iterator], [context])
- Alias: some
-
- Returns true if any of the values in the list pass the
- iterator truth test. Short-circuits and stops traversing the list
- if a true element is found. Delegates to the native method some,
- if present.
-
-_.any([null, 0, 'yes', false]); -=> true -- -
- include_.include(list, value)
- Alias: contains
-
- Returns true if the value is present in the list, using
- === to test equality. Uses indexOf internally, if list
- is an Array.
-
-_.include([1, 2, 3], 3); -=> true -- -
- invoke_.invoke(list, methodName, [*arguments])
-
- Calls the method named by methodName on each value in the list.
- Any extra arguments passed to invoke will be forwarded on to the
- method invocation.
-
-_.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); -=> [[1, 5, 7], [1, 2, 3]] -- -
- pluck_.pluck(list, propertyName)
-
- A convenient version of what is perhaps the most common use-case for
- map: extracting a list of property values.
-
-var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
-_.pluck(stooges, 'name');
-=> ["moe", "larry", "curly"]
-
-
-
- max_.max(list, [iterator], [context])
-
- Returns the maximum value in list. If iterator is passed,
- it will be used on each value to generate the criterion by which the
- value is ranked.
-
-var stooges = [{name : 'moe', age : 40}, {name : 'larry', age : 50}, {name : 'curly', age : 60}];
-_.max(stooges, function(stooge){ return stooge.age; });
-=> {name : 'curly', age : 60};
-
-
-
- min_.min(list, [iterator], [context])
-
- Returns the minimum value in list. If iterator is passed,
- it will be used on each value to generate the criterion by which the
- value is ranked.
-
-var numbers = [10, 5, 100, 2, 1000]; -_.min(numbers); -=> 2 -- -
- sortBy_.sortBy(list, iterator, [context])
-
- Returns a sorted copy of list, ranked in ascending order by the
- results of running each value through iterator. Iterator may
- also be the string name of the property to sort by (eg. length).
-
-_.sortBy([1, 2, 3, 4, 5, 6], function(num){ return Math.sin(num); });
-=> [5, 4, 6, 3, 1, 2]
-
-
-
- groupBy_.groupBy(list, iterator)
-
- Splits a collection into sets, grouped by the result of running each
- value through iterator. If iterator is a string instead of
- a function, groups by the property named by iterator on each of
- the values.
-
-_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
-=> {1: [1.3], 2: [2.1, 2.4]}
-
-_.groupBy(['one', 'two', 'three'], 'length');
-=> {3: ["one", "two"], 5: ["three"]}
-
-
-
- sortedIndex_.sortedIndex(list, value, [iterator])
-
- Uses a binary search to determine the index at which the value
- should be inserted into the list in order to maintain the list's
- sorted order. If an iterator is passed, it will be used to compute
- the sort ranking of each value.
-
-_.sortedIndex([10, 20, 30, 40, 50], 35); -=> 3 -- -
- shuffle_.shuffle(list)
-
- Returns a shuffled copy of the list, using a version of the
- Fisher-Yates shuffle.
-
-_.shuffle([1, 2, 3, 4, 5, 6]); -=> [4, 1, 6, 3, 5, 2] -- -
- toArray_.toArray(list)
-
- Converts the list (anything that can be iterated over), into a
- real Array. Useful for transmuting the arguments object.
-
-(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
-=> [2, 3, 4]
-
-
-
- size_.size(list)
-
- Return the number of values in the list.
-
-_.size({one : 1, two : 2, three : 3});
-=> 3
-
-
- - Note: All array functions will also work on the arguments object. -
- -
- first_.first(array, [n])
- Alias: head
-
- Returns the first element of an array. Passing n will
- return the first n elements of the array.
-
-_.first([5, 4, 3, 2, 1]); -=> 5 -- -
- initial_.initial(array, [n])
-
- Returns everything but the last entry of the array. Especially useful on
- the arguments object. Pass n to exclude the last n elements
- from the result.
-
-_.initial([5, 4, 3, 2, 1]); -=> [5, 4, 3, 2] -- -
- last_.last(array, [n])
-
- Returns the last element of an array. Passing n will return
- the last n elements of the array.
-
-_.last([5, 4, 3, 2, 1]); -=> 1 -- -
- rest_.rest(array, [index])
- Alias: tail
-
- Returns the rest of the elements in an array. Pass an index
- to return the values of the array from that index onward.
-
-_.rest([5, 4, 3, 2, 1]); -=> [4, 3, 2, 1] -- -
- compact_.compact(array)
-
- Returns a copy of the array with all falsy values removed.
- In JavaScript, false, null, 0, "",
- undefined and NaN are all falsy.
-
-_.compact([0, 1, false, 2, '', 3]); -=> [1, 2, 3] -- -
- flatten_.flatten(array, [shallow])
-
- Flattens a nested array (the nesting can be to any depth). If you
- pass shallow, the array will only be flattened a single level.
-
-_.flatten([1, [2], [3, [[4]]]]); -=> [1, 2, 3, 4]; - -_.flatten([1, [2], [3, [[4]]]], true); -=> [1, 2, 3, [[4]]]; -- -
- without_.without(array, [*values])
-
- Returns a copy of the array with all instances of the values
- removed. === is used for the equality test.
-
-_.without([1, 2, 1, 0, 3, 1, 4], 0, 1); -=> [2, 3, 4] -- -
- union_.union(*arrays)
-
- Computes the union of the passed-in arrays: the list of unique items,
- in order, that are present in one or more of the arrays.
-
-_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); -=> [1, 2, 3, 101, 10] -- -
- intersection_.intersection(*arrays)
-
- Computes the list of values that are the intersection of all the arrays.
- Each value in the result is present in each of the arrays.
-
-_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); -=> [1, 2] -- -
- difference_.difference(array, *others)
-
- Similar to without, but returns the values from array that
- are not present in the other arrays.
-
-_.difference([1, 2, 3, 4, 5], [5, 2, 10]); -=> [1, 3, 4] -- -
- uniq_.uniq(array, [isSorted], [iterator])
- Alias: unique
-
- Produces a duplicate-free version of the array, using === to test
- object equality. If you know in advance that the array is sorted,
- passing true for isSorted will run a much faster algorithm.
- If you want to compute unique items based on a transformation, pass an
- iterator function.
-
-_.uniq([1, 2, 1, 3, 1, 4]); -=> [1, 2, 3, 4] -- -
- zip_.zip(*arrays)
-
- Merges together the values of each of the arrays with the
- values at the corresponding position. Useful when you have separate
- data sources that are coordinated through matching array indexes.
- If you're working with a matrix of nested arrays, zip.apply
- can transpose the matrix in a similar fashion.
-
-_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]); -=> [["moe", 30, true], ["larry", 40, false], ["curly", 50, false]] -- -
- indexOf_.indexOf(array, value, [isSorted])
-
- Returns the index at which value can be found in the array,
- or -1 if value is not present in the array. Uses the native
- indexOf function unless it's missing. If you're working with a
- large array, and you know that the array is already sorted, pass true
- for isSorted to use a faster binary search.
-
-_.indexOf([1, 2, 3], 2); -=> 1 -- -
- lastIndexOf_.lastIndexOf(array, value)
-
- Returns the index of the last occurrence of value in the array,
- or -1 if value is not present. Uses the native lastIndexOf
- function if possible.
-
-_.lastIndexOf([1, 2, 3, 1, 2, 3], 2); -=> 4 -- -
- range_.range([start], stop, [step])
-
- A function to create flexibly-numbered lists of integers, handy for
- each and map loops. start, if omitted, defaults
- to 0; step defaults to 1. Returns a list of integers
- from start to stop, incremented (or decremented) by step,
- exclusive.
-
-_.range(10); -=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] -_.range(1, 11); -=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -_.range(0, 30, 5); -=> [0, 5, 10, 15, 20, 25] -_.range(0, -10, -1); -=> [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] -_.range(0); -=> [] -- -
- bind_.bind(function, object, [*arguments])
-
- Bind a function to an object, meaning that whenever
- the function is called, the value of this will be the object.
- Optionally, bind arguments to the function to pre-fill them,
- also known as partial application.
-
-var func = function(greeting){ return greeting + ': ' + this.name };
-func = _.bind(func, {name : 'moe'}, 'hi');
-func();
-=> 'hi: moe'
-
-
-
- bindAll_.bindAll(object, [*methodNames])
-
- Binds a number of methods on the object, specified by
- methodNames, to be run in the context of that object whenever they
- are invoked. Very handy for binding functions that are going to be used
- as event handlers, which would otherwise be invoked with a fairly useless
- this. If no methodNames are provided, all of the object's
- function properties will be bound to it.
-
-var buttonView = {
- label : 'underscore',
- onClick : function(){ alert('clicked: ' + this.label); },
- onHover : function(){ console.log('hovering: ' + this.label); }
-};
-_.bindAll(buttonView);
-jQuery('#underscore_button').bind('click', buttonView.onClick);
-=> When the button is clicked, this.label will have the correct value...
-
-
-
- memoize_.memoize(function, [hashFunction])
-
- Memoizes a given function by caching the computed result. Useful
- for speeding up slow-running computations. If passed an optional
- hashFunction, it will be used to compute the hash key for storing
- the result, based on the arguments to the original function. The default
- hashFunction just uses the first argument to the memoized function
- as the key.
-
-var fibonacci = _.memoize(function(n) {
- return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
-});
-
-
-
- delay_.delay(function, wait, [*arguments])
-
- Much like setTimeout, invokes function after wait
- milliseconds. If you pass the optional arguments, they will be
- forwarded on to the function when it is invoked.
-
-var log = _.bind(console.log, console); -_.delay(log, 1000, 'logged later'); -=> 'logged later' // Appears after one second. -- -
- defer_.defer(function)
-
- Defers invoking the function until the current call stack has cleared,
- similar to using setTimeout with a delay of 0. Useful for performing
- expensive computations or HTML rendering in chunks without blocking the UI thread
- from updating.
-
-_.defer(function(){ alert('deferred'); });
-// Returns from the function before the alert runs.
-
-
-
- throttle_.throttle(function, wait)
-
- Creates and returns a new, throttled version of the passed function,
- that, when invoked repeatedly, will only actually call the original function
- at most once per every wait
- milliseconds. Useful for rate-limiting events that occur faster than you
- can keep up with.
-
-var throttled = _.throttle(updatePosition, 100); -$(window).scroll(throttled); -- -
- debounce_.debounce(function, wait, [immediate])
-
- Creates and returns a new debounced version of the passed function that
- will postpone its execution until after
- wait milliseconds have elapsed since the last time it
- was invoked. Useful for implementing behavior that should only happen
- after the input has stopped arriving. For example: rendering a
- preview of a Markdown comment, recalculating a layout after the window
- has stopped being resized, and so on.
-
- Pass true for the immediate parameter to cause - debounce to trigger the function on the leading intead of the - trailing edge of the wait interval. Useful in circumstances like - preventing accidental double-clicks on a "submit" button from firing a - second time. -
- --var lazyLayout = _.debounce(calculateLayout, 300); -$(window).resize(lazyLayout); -- -
- once_.once(function)
-
- Creates a version of the function that can only be called one time.
- Repeated calls to the modified function will have no effect, returning
- the value from the original call. Useful for initialization functions,
- instead of having to set a boolean flag and then check it later.
-
-var initialize = _.once(createApplication); -initialize(); -initialize(); -// Application is only created once. -- -
- after_.after(count, function)
-
- Creates a version of the function that will only be run after first
- being called count times. Useful for grouping asynchronous responses,
- where you want to be sure that all the async calls have finished, before
- proceeding.
-
-var renderNotes = _.after(notes.length, render);
-_.each(notes, function(note) {
- note.asyncSave({success: renderNotes});
-});
-// renderNotes is run once, after all notes have saved.
-
-
-
- wrap_.wrap(function, wrapper)
-
- Wraps the first function inside of the wrapper function,
- passing it as the first argument. This allows the wrapper to
- execute code before and after the function runs, adjust the arguments,
- and execute it conditionally.
-
-var hello = function(name) { return "hello: " + name; };
-hello = _.wrap(hello, function(func) {
- return "before, " + func("moe") + ", after";
-});
-hello();
-=> 'before, hello: moe, after'
-
-
-
- compose_.compose(*functions)
-
- Returns the composition of a list of functions, where each function
- consumes the return value of the function that follows. In math terms,
- composing the functions f(), g(), and h() produces
- f(g(h())).
-
-var greet = function(name){ return "hi: " + name; };
-var exclaim = function(statement){ return statement + "!"; };
-var welcome = _.compose(exclaim, greet);
-welcome('moe');
-=> 'hi: moe!'
-
-
-
- keys_.keys(object)
-
- Retrieve all the names of the object's properties.
-
-_.keys({one : 1, two : 2, three : 3});
-=> ["one", "two", "three"]
-
-
-
- values_.values(object)
-
- Return all of the values of the object's properties.
-
-_.values({one : 1, two : 2, three : 3});
-=> [1, 2, 3]
-
-
-
- functions_.functions(object)
- Alias: methods
-
- Returns a sorted list of the names of every method in an object —
- that is to say, the name of every function property of the object.
-
-_.functions(_); -=> ["all", "any", "bind", "bindAll", "clone", "compact", "compose" ... -- -
- extend_.extend(destination, *sources)
-
- Copy all of the properties in the source objects over to the
- destination object, and return the destination object.
- It's in-order, so the last source will override properties of the same
- name in previous arguments.
-
-_.extend({name : 'moe'}, {age : 50});
-=> {name : 'moe', age : 50}
-
-
-
- pick_.pick(object, *keys)
-
- Return a copy of the object, filtered to only have values for
- the whitelisted keys (or array of valid keys).
-
-_.pick({name : 'moe', age: 50, userid : 'moe1'}, 'name', 'age');
-=> {name : 'moe', age : 50}
-
-
-
- defaults_.defaults(object, *defaults)
-
- Fill in missing properties in object with default values from the
- defaults objects, and return the object. As soon as the
- property is filled, further defaults will have no effect.
-
-var iceCream = {flavor : "chocolate"};
-_.defaults(iceCream, {flavor : "vanilla", sprinkles : "lots"});
-=> {flavor : "chocolate", sprinkles : "lots"}
-
-
-
- clone_.clone(object)
-
- Create a shallow-copied clone of the object. Any nested objects
- or arrays will be copied by reference, not duplicated.
-
-_.clone({name : 'moe'});
-=> {name : 'moe'};
-
-
-
- tap_.tap(object, interceptor)
-
- Invokes interceptor with the object, and then returns object.
- The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
-
-_.chain([1,2,3,200])
- .filter(function(num) { return num % 2 == 0; })
- .tap(alert)
- .map(function(num) { return num * num })
- .value();
-=> // [2, 200] (alerted)
-=> [4, 40000]
-
-
-
- has_.has(object, key)
-
- Does the object contain the given key? Identical to
- object.hasOwnProperty(key), but uses a safe reference to the
- hasOwnProperty function, in case it's been
- overridden accidentally.
-
-_.has({a: 1, b: 2, c: 3}, "b");
-=> true
-
-
-
- isEqual_.isEqual(object, other)
-
- Performs an optimized deep comparison between the two objects, to determine
- if they should be considered equal.
-
-var moe = {name : 'moe', luckyNumbers : [13, 27, 34]};
-var clone = {name : 'moe', luckyNumbers : [13, 27, 34]};
-moe == clone;
-=> false
-_.isEqual(moe, clone);
-=> true
-
-
-
- isEmpty_.isEmpty(object)
-
- Returns true if object contains no values.
-
-_.isEmpty([1, 2, 3]);
-=> false
-_.isEmpty({});
-=> true
-
-
-
- isElement_.isElement(object)
-
- Returns true if object is a DOM element.
-
-_.isElement(jQuery('body')[0]);
-=> true
-
-
-
- isArray_.isArray(object)
-
- Returns true if object is an Array.
-
-(function(){ return _.isArray(arguments); })();
-=> false
-_.isArray([1,2,3]);
-=> true
-
-
-
- isObject_.isObject(value)
-
- Returns true if value is an Object.
-
-_.isObject({});
-=> true
-_.isObject(1);
-=> false
-
-
-
- isArguments_.isArguments(object)
-
- Returns true if object is an Arguments object.
-
-(function(){ return _.isArguments(arguments); })(1, 2, 3);
-=> true
-_.isArguments([1,2,3]);
-=> false
-
-
-
- isFunction_.isFunction(object)
-
- Returns true if object is a Function.
-
-_.isFunction(alert); -=> true -- -
- isString_.isString(object)
-
- Returns true if object is a String.
-
-_.isString("moe");
-=> true
-
-
-
- isNumber_.isNumber(object)
-
- Returns true if object is a Number (including NaN).
-
-_.isNumber(8.4 * 5); -=> true -- -
- isFinite_.isFinite(object)
-
- Returns true if object is a finite Number.
-
-_.isFinite(-101); -=> true - -_.isFinite(-Infinity); -=> false -- -
- isBoolean_.isBoolean(object)
-
- Returns true if object is either true or false.
-
-_.isBoolean(null); -=> false -- -
- isDate_.isDate(object)
-
- Returns true if object is a Date.
-
-_.isDate(new Date()); -=> true -- -
- isRegExp_.isRegExp(object)
-
- Returns true if object is a RegExp.
-
-_.isRegExp(/moe/); -=> true -- -
- isNaN_.isNaN(object)
-
- Returns true if object is NaN.
Note: this is not
- the same as the native isNaN function, which will also return
- true if the variable is undefined.
-
-_.isNaN(NaN); -=> true -isNaN(undefined); -=> true -_.isNaN(undefined); -=> false -- -
- isNull_.isNull(object)
-
- Returns true if the value of object is null.
-
-_.isNull(null); -=> true -_.isNull(undefined); -=> false -- -
- isUndefined_.isUndefined(variable)
-
- Returns true if variable is undefined.
-
-_.isUndefined(window.missingVariable); -=> true -- -
- noConflict_.noConflict()
-
- Give control of the "_" variable back to its previous owner. Returns
- a reference to the Underscore object.
-
-var underscore = _.noConflict();- -
- identity_.identity(value)
-
- Returns the same value that is used as the argument. In math:
- f(x) = x
- This function looks useless, but is used throughout Underscore as
- a default iterator.
-
-var moe = {name : 'moe'};
-moe === _.identity(moe);
-=> true
-
-
- times_.times(n, iterator)
-
- Invokes the given iterator function n times.
-
-_(3).times(function(){ genie.grantWish(); });
-
-
- mixin_.mixin(object)
-
- Allows you to extend Underscore with your own utility functions. Pass
- a hash of {name: function} definitions to have your functions
- added to the Underscore object, as well as the OOP wrapper.
-
-_.mixin({
- capitalize : function(string) {
- return string.charAt(0).toUpperCase() + string.substring(1).toLowerCase();
- }
-});
-_("fabio").capitalize();
-=> "Fabio"
-
-
-
- uniqueId_.uniqueId([prefix])
-
- Generate a globally-unique id for client-side models or DOM elements
- that need one. If prefix is passed, the id will be appended to it.
- Without prefix, returns an integer.
-
-_.uniqueId('contact_');
-=> 'contact_104'
-
-
- escape_.escape(string)
-
- Escapes a string for insertion into HTML, replacing
- &, <, >, ", ', and / characters.
-
-_.escape('Curly, Larry & Moe');
-=> "Curly, Larry & Moe"
-
-
- result_.result(object, property)
-
- If the value of the named property is a function then invoke it; otherwise, return it.
-
-var object = {cheese: 'crumpets', stuff: function(){ return 'nonsense'; }};
-_.result(object, 'cheese');
-=> "crumpets"
-_.result(object, 'stuff');
-=> "nonsense"
-
-
- template_.template(templateString, [data], [settings])
-
- Compiles JavaScript templates into functions that can be evaluated
- for rendering. Useful for rendering complicated bits of HTML from JSON
- data sources. Template functions can both interpolate variables, using
- <%= … %>, as well as execute arbitrary JavaScript code, with
- <% … %>. If you wish to interpolate a value, and have
- it be HTML-escaped, use <%- … %> When you evaluate a template function, pass in a
- data object that has properties corresponding to the template's free
- variables. If you're writing a one-off, you can pass the data
- object as the second parameter to template in order to render
- immediately instead of returning a template function. The settings argument
- should be a hash containing any _.templateSettings that should be overriden.
-
-var compiled = _.template("hello: <%= name %>");
-compiled({name : 'moe'});
-=> "hello: moe"
-
-var list = "<% _.each(people, function(name) { %> <li><%= name %></li> <% }); %>";
-_.template(list, {people : ['moe', 'curly', 'larry']});
-=> "<li>moe</li><li>curly</li><li>larry</li>"
-
-var template = _.template("<b><%- value %></b>");
-template({value : '<script>'});
-=> "<b><script></b>"
-
- - You can also use print from within JavaScript code. This is - sometimes more convenient than using <%= ... %>. -
- -
-var compiled = _.template("<% print('Hello ' + epithet); %>");
-compiled({epithet: "stooge"});
-=> "Hello stooge."
-
- - If ERB-style delimiters aren't your cup of tea, you can change Underscore's - template settings to use different symbols to set off interpolated code. - Define an interpolate regex to match expressions that should be - interpolated verbatim, an escape regex to match expressions that should - be inserted after being HTML escaped, and an evaluate regex to match - expressions that should be evaluated without insertion into the resulting - string. You may define or omit any combination of the three. - For example, to perform - Mustache.js - style templating: -
- -
-_.templateSettings = {
- interpolate : /\{\{(.+?)\}\}/g
-};
-
-var template = _.template("Hello {{ name }}!");
-template({name : "Mustache"});
-=> "Hello Mustache!"
-
- - By default, template places the values from your data in the local scope - via the with statement. However, you can specify a single variable name - with the variable setting. This can significantly improve the speed - at which a template is able to render. -
- -
-_.template("<%= data.hasWith %>", {hasWith: 'no'}, {variable: 'data'});
-=> "no"
-
- - Precompiling your templates can be a big help when debugging errors you can't - reproduce. This is because precompiled templates can provide line numbers and - a stack trace, something that is not possible when compiling templates on the client. - The source property is available on the compiled template - function for easy precompilation. -
- -<script> - JST.project = <%= _.template(jstText).source %>; -</script>- - -
- You can use Underscore in either an object-oriented or a functional style, - depending on your preference. The following two lines of code are - identical ways to double a list of numbers. -
- -
-_.map([1, 2, 3], function(n){ return n * 2; });
-_([1, 2, 3]).map(function(n){ return n * 2; });
-
- - Calling chain on a wrapped object will cause all future method calls to - return wrapped objects as well. When you've finished the computation, - use value to retrieve the final value. Here's an example of chaining - together a map/flatten/reduce, in order to get the word count of - every word in a song. -
- -
-var lyrics = [
- {line : 1, words : "I'm a lumberjack and I'm okay"},
- {line : 2, words : "I sleep all night and I work all day"},
- {line : 3, words : "He's a lumberjack and he's okay"},
- {line : 4, words : "He sleeps all night and he works all day"}
-];
-
-_.chain(lyrics)
- .map(function(line) { return line.words.split(' '); })
- .flatten()
- .reduce(function(counts, word) {
- counts[word] = (counts[word] || 0) + 1;
- return counts;
-}, {}).value();
-
-=> {lumberjack : 2, all : 4, night : 2 ... }
-
- - In addition, the - Array prototype's methods - are proxied through the chained Underscore object, so you can slip a - reverse or a push into your chain, and continue to - modify the array. -
- -
- chain_.chain(obj)
-
- Returns a wrapped object. Calling methods on this object will continue
- to return wrapped objects until value is used.
-
-var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}];
-var youngest = _.chain(stooges)
- .sortBy(function(stooge){ return stooge.age; })
- .map(function(stooge){ return stooge.name + ' is ' + stooge.age; })
- .first()
- .value();
-=> "moe is 21"
-
-
-
- value_(obj).value()
-
- Extracts the value of a wrapped object.
-
-_([1, 2, 3]).value(); -=> [1, 2, 3] -- -
- Underscore.lua, - a Lua port of the functions that are applicable in both languages. - Includes OOP-wrapping and chaining. - The source is - available on GitHub. -
- -- Underscore.php, - a PHP port of the functions that are applicable in both languages. - Includes OOP-wrapping and chaining. - The source is - available on GitHub. -
- -- Underscore-perl, - a Perl port of many of the Underscore.js functions, - aimed at on Perl hashes and arrays, also - available on GitHub. -
- -- Underscore.string, - an Underscore extension that adds functions for string-manipulation: - trim, startsWith, contains, capitalize, - reverse, sprintf, and more. -
- -- Ruby's Enumerable module. -
- -- Prototype.js, which provides - JavaScript with collection functions in the manner closest to Ruby's Enumerable. -
- -- Oliver Steele's - Functional JavaScript, - which includes comprehensive higher-order function support as well as string lambdas. -
- -- Michael Aufreiter's Data.js, - a data manipulation + persistence library for JavaScript. -
- -- Python's itertools. -
- -
- 1.3.3 — April 10, 2012
-
- 1.3.1 — Jan. 23, 2012
-
- 1.3.0 — Jan. 11, 2012
-
- 1.2.4 — Jan. 4, 2012
-
- 1.2.3 — Dec. 7, 2011
-
- 1.2.2 — Nov. 14, 2011
-
- 1.2.1 — Oct. 24, 2011
-
- 1.2.0 — Oct. 5, 2011
-
- 1.1.7 — July 13, 2011
- Added _.groupBy, which aggregates a collection into groups of like items.
- Added _.union and _.difference, to complement the
- (re-named) _.intersection.
- Various improvements for support of sparse arrays.
- _.toArray now returns a clone, if directly passed an array.
- _.functions now also returns the names of functions that are present
- in the prototype chain.
-
- 1.1.6 — April 18, 2011
- Added _.after, which will return a function that only runs after
- first being called a specified number of times.
- _.invoke can now take a direct function reference.
- _.every now requires an iterator function to be passed, which
- mirrors the ECMA5 API.
- _.extend no longer copies keys when the value is undefined.
- _.bind now errors when trying to bind an undefined value.
-
- 1.1.5 — Mar 20, 2011
- Added an _.defaults function, for use merging together JS objects
- representing default options.
- Added an _.once function, for manufacturing functions that should
- only ever execute a single time.
- _.bind now delegates to the native ECMAScript 5 version,
- where available.
- _.keys now throws an error when used on non-Object values, as in
- ECMAScript 5.
- Fixed a bug with _.keys when used over sparse arrays.
-
- 1.1.4 — Jan 9, 2011
- Improved compliance with ES5's Array methods when passing null
- as a value. _.wrap now correctly sets this for the
- wrapped function. _.indexOf now takes an optional flag for
- finding the insertion index in an array that is guaranteed to already
- be sorted. Avoiding the use of .callee, to allow _.isArray
- to work properly in ES5's strict mode.
-
- 1.1.3 — Dec 1, 2010
- In CommonJS, Underscore may now be required with just:
- var _ = require("underscore").
- Added _.throttle and _.debounce functions.
- Removed _.breakLoop, in favor of an ECMA5-style un-break-able
- each implementation — this removes the try/catch, and you'll now have
- better stack traces for exceptions that are thrown within an Underscore iterator.
- Improved the isType family of functions for better interoperability
- with Internet Explorer host objects.
- _.template now correctly escapes backslashes in templates.
- Improved _.reduce compatibility with the ECMA5 version:
- if you don't pass an initial value, the first item in the collection is used.
- _.each no longer returns the iterated collection, for improved
- consistency with ES5's forEach.
-
- 1.1.2
- Fixed _.contains, which was mistakenly pointing at
- _.intersect instead of _.include, like it should
- have been. Added _.unique as an alias for _.uniq.
-
- 1.1.1
- Improved the speed of _.template, and its handling of multiline
- interpolations. Ryan Tenney contributed optimizations to many Underscore
- functions. An annotated version of the source code is now available.
-
- 1.1.0
- The method signature of _.reduce has been changed to match
- the ECMAScript 5 signature, instead of the Ruby/Prototype.js version.
- This is a backwards-incompatible change. _.template may now be
- called with no arguments, and preserves whitespace. _.contains
- is a new alias for _.include.
-
- 1.0.4
- Andri Möll contributed the _.memoize
- function, which can be used to speed up expensive repeated computations
- by caching the results.
-
- 1.0.3
- Patch that makes _.isEqual return false if any property
- of the compared object has a NaN value. Technically the correct
- thing to do, but of questionable semantics. Watch out for NaN comparisons.
-
- 1.0.2
- Fixes _.isArguments in recent versions of Opera, which have
- arguments objects as real Arrays.
-
- 1.0.1
- Bugfix for _.isEqual, when comparing two objects with the same
- number of undefined keys, but with different names.
-
- 1.0.0
- Things have been stable for many months now, so Underscore is now
- considered to be out of beta, at 1.0. Improvements since 0.6
- include _.isBoolean, and the ability to have _.extend
- take multiple source objects.
-
- 0.6.0
- Major release. Incorporates a number of
- Mile Frawley's refactors for
- safer duck-typing on collection functions, and cleaner internals. A new
- _.mixin method that allows you to extend Underscore with utility
- functions of your own. Added _.times, which works the same as in
- Ruby or Prototype.js. Native support for ECMAScript 5's Array.isArray,
- and Object.keys.
-
- 0.5.8
- Fixed Underscore's collection functions to work on
- NodeLists and
- HTMLCollections
- once more, thanks to
- Justin Tulloss.
-
- 0.5.7
- A safer implementation of _.isArguments, and a
- faster _.isNumber,
thanks to
- Jed Schmidt.
-
- 0.5.6
- Customizable delimiters for _.template, contributed by
- Noah Sloan.
-
- 0.5.5
- Fix for a bug in MobileSafari's OOP-wrapper, with the arguments object.
-
- 0.5.4
- Fix for multiple single quotes within a template string for
- _.template. See:
- Rick Strahl's blog post.
-
- 0.5.2
- New implementations of isArray, isDate, isFunction,
- isNumber, isRegExp, and isString, thanks to
- a suggestion from
- Robert Kieffer.
- Instead of doing Object#toString
- comparisons, they now check for expected properties, which is less safe,
- but more than an order of magnitude faster. Most other Underscore
- functions saw minor speed improvements as a result.
- Evgeniy Dolzhenko
- contributed _.tap,
- similar to Ruby 1.9's,
- which is handy for injecting side effects (like logging) into chained calls.
-
- 0.5.1
- Added an _.isArguments function. Lots of little safety checks
- and optimizations contributed by
- Noah Sloan and
- Andri Möll.
-
- 0.5.0
- [API Changes] _.bindAll now takes the context object as
- its first parameter. If no method names are passed, all of the context
- object's methods are bound to it, enabling chaining and easier binding.
- _.functions now takes a single argument and returns the names
- of its Function properties. Calling _.functions(_) will get you
- the previous behavior.
- Added _.isRegExp so that isEqual can now test for RegExp equality.
- All of the "is" functions have been shrunk down into a single definition.
- Karl Guertin contributed patches.
-
- 0.4.7
- Added isDate, isNaN, and isNull, for completeness.
- Optimizations for isEqual when checking equality between Arrays
- or Dates. _.keys is now 25%–2X faster (depending on your
- browser) which speeds up the functions that rely on it, such as _.each.
-
- 0.4.6
- Added the range function, a port of the
- Python
- function of the same name, for generating flexibly-numbered lists
- of integers. Original patch contributed by
- Kirill Ishanov.
-
- 0.4.5
- Added rest for Arrays and arguments objects, and aliased
- first as head, and rest as tail,
- thanks to Luke Sutton's patches.
- Added tests ensuring that all Underscore Array functions also work on
- arguments objects.
-
- 0.4.4
- Added isString, and isNumber, for consistency. Fixed
- _.isEqual(NaN, NaN) to return true (which is debatable).
-
- 0.4.3
- Started using the native StopIteration object in browsers that support it.
- Fixed Underscore setup for CommonJS environments.
-
- 0.4.2
- Renamed the unwrapping function to value, for clarity.
-
- 0.4.1
- Chained Underscore objects now support the Array prototype methods, so
- that you can perform the full range of operations on a wrapped array
- without having to break your chain. Added a breakLoop method
- to break in the middle of any Underscore iteration. Added an
- isEmpty function that works on arrays and objects.
-
- 0.4.0
- All Underscore functions can now be called in an object-oriented style,
- like so: _([1, 2, 3]).map(...);. Original patch provided by
- Marc-André Cournoyer.
- Wrapped objects can be chained through multiple
- method invocations. A functions method
- was added, providing a sorted list of all the functions in Underscore.
-
- 0.3.3
- Added the JavaScript 1.8 function reduceRight. Aliased it
- as foldr, and aliased reduce as foldl.
-
- 0.3.2
- Now runs on stock Rhino
- interpreters with: load("underscore.js").
- Added identity as a utility function.
-
- 0.3.1
- All iterators are now passed in the original collection as their third
- argument, the same as JavaScript 1.6's forEach. Iterating over
- objects is now called with (value, key, collection), for details
- see _.each.
-
- 0.3.0
- Added Dmitry Baranovskiy's
- comprehensive optimizations, merged in
- Kris Kowal's patches to make Underscore
- CommonJS and
- Narwhal compliant.
-
- 0.2.0
- Added compose and lastIndexOf, renamed inject to
- reduce, added aliases for inject, filter,
- every, some, and forEach.
-
- 0.1.1
- Added noConflict, so that the "Underscore" object can be assigned to
- other variables.
-
- 0.1.0
- Initial release of Underscore.js.
-
-
-
-
-