diff --git a/index.html b/index.html new file mode 100644 index 000000000..aae21514d --- /dev/null +++ b/index.html @@ -0,0 +1,308 @@ + + + + Underscore.js + + + + +
+ +

Underscore.js

+ +

+ 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. +

+ +

+ Underscore provides 43-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 the built-in + functions, if present, so + Javascript 1.6 + compliant browsers will use the + native implementations of forEach, map, filter, + every and some. +

+ +

+ Underscore includes a complete Test & Benchmark Suite + for your perusal. +

+ +

Table of Contents

+ +

+ Collections +
+ each, map, + inject, detect, select, reject, all, + any, include, invoke, pluck, max, + min, sortBy, sortedIndex, toArray, + size +

+ +

+ Arrays +
+ first, last, + compact, flatten, without, uniq, + intersect, zip, indexOf +

+ +

+ Objects +
+ keys, values, + extend, clone, isEqual, isElement, + isArray, isFunction, isUndefined, toString + +

+ +

+ Functions +
+ bind, bindAll, delay, + defer, wrap +

+ +

+ Utility +
+ uniqueId, template +

+ +
+

Collections

+ +

+ each_.each(list, iterator, [context]) +
+ 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. If list is a Javascript object, a pair with key + and value properties will be yielded. Delegates to the native + forEach method if it exists. +

+
+_.each([1, 2, 3], function(num){ alert(num); });
+=> alerts each number in turn...
+ +

+ map_.map(list, iterator, [context]) +
+ 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. +

+
+_.map([1, 2, 3], function(num){ return num * 3 });
+=> [3, 6, 9]
+ +

+ inject_.inject(list, memo, iterator, [context]) +
+ Also known as reduce and foldl, inject reduces 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 = _.inject([1, 2, 3], 0, function(memo, num){ return memo + num });
+=> 6
+
+ +

+ detect_.detect(list, iterator, [context]) +
+ 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 the true element, and doesn't continue to traverse + the list. +

+
+var even = _.detect([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> 2
+
+ +

+ select_.select(list, iterator, [context]) +
+ 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 = _.select([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 select. +

+
+var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
+=> [1, 3, 5]
+
+ +

+ all_.(list, [iterator], [context]) +
+ Returns true if all of the values in the list pass the iterator + truth test. If an iterator is not provided, the truthy value of + the element will be used instead. Delegates to the native method every, if + present. +

+
+_.all([true, 1, null, 'yes']);
+=> false
+
+ +

+ any_.(list, iterator, [context]) +
+ 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_.(list, iterator, [context]) +
+ +

+
+
+ +

+ invoke_.(list, iterator, [context]) +
+ +

+
+
+ +

+ pluck_.(list, iterator, [context]) +
+ +

+
+
+ +

+ max_.(list, iterator, [context]) +
+ +

+
+
+ +

+ min_.(list, iterator, [context]) +
+ +

+
+
+ +

+ sortBy_.(list, iterator, [context]) +
+ +

+
+
+ +

+ sortedIndex_.(list, iterator, [context]) +
+ +

+
+
+ +

+ toArray_.(list, iterator, [context]) +
+ +

+
+
+ +

+ size_.(list, iterator, [context]) +
+ +

+
+
+ +
+ +
+ + + diff --git a/test/functions.js b/test/functions.js index 47de34699..039f7a746 100644 --- a/test/functions.js +++ b/test/functions.js @@ -29,4 +29,23 @@ $(document).ready(function() { equals(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object'); }); + asyncTest("functions: delay", function() { + var delayed = false; + _.delay(function(){ delayed = true; }, 100); + _.delay(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50); + _.delay(function(){ ok(delayed, 'delayed the function'); start(); }, 150); + }); + + asyncTest("functions: defer", function() { + var deferred = false; + _.defer(function(bool){ deferred = bool; }, true); + _.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50); + }); + + test("functions: wrap", function() { + var greet = function(name){ return "hi: " + name; }; + var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); }); + equals(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function'); + }); + }); diff --git a/test/test.html b/test/test.html index 67415345d..aa2ca7a12 100644 --- a/test/test.html +++ b/test/test.html @@ -9,8 +9,8 @@ - + diff --git a/underscore.js b/underscore.js index 8f4ba6ee4..7c5ee29cb 100644 --- a/underscore.js +++ b/underscore.js @@ -283,6 +283,29 @@ window._ = { }); }, + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + delay : function(func, wait) { + var args = _.toArray(arguments).slice(2); + return window.setTimeout(function(){ return func.apply(func, 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(_.toArray(arguments).slice(1))); + }, + + // 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(_.toArray(arguments)); + return wrapper.apply(wrapper, args); + }; + }, + /* ---------------- The following methods apply to objects ---------------- */ // Retrieve the names of an object's properties.