WordPress source code - trunk (underscore-1.4.1.js)

//     Underscore.js 1.4.1
2	//     http://underscorejs.org
3	//     (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
4	//     Underscore may be freely distributed under the MIT license.
5	
6	(function() {
7	
8	  // Baseline setup
9	  // --------------
10	
11	  // Establish the root object, `window` in the browser, or `global` on the server.
12	  var root = this;
13	
14	  // Save the previous value of the `_` variable.
15	  var previousUnderscore = root._;
16	
17	  // Establish the object that gets returned to break out of a loop iteration.
18	  var breaker = {};
19	
20	  // Save bytes in the minified (but not gzipped) version:
21	  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
22	
23	  // Create quick reference variables for speed access to core prototypes.
24	  var push             = ArrayProto.push,
25	      slice            = ArrayProto.slice,
26	      concat           = ArrayProto.concat,
27	      unshift          = ArrayProto.unshift,
28	      toString         = ObjProto.toString,
29	      hasOwnProperty   = ObjProto.hasOwnProperty;
30	
31	  // All **ECMAScript 5** native function implementations that we hope to use
32	  // are declared here.
33	  var
34	    nativeForEach      = ArrayProto.forEach,
35	    nativeMap          = ArrayProto.map,
36	    nativeReduce       = ArrayProto.reduce,
37	    nativeReduceRight  = ArrayProto.reduceRight,
38	    nativeFilter       = ArrayProto.filter,
39	    nativeEvery        = ArrayProto.every,
40	    nativeSome         = ArrayProto.some,
41	    nativeIndexOf      = ArrayProto.indexOf,
42	    nativeLastIndexOf  = ArrayProto.lastIndexOf,
43	    nativeIsArray      = Array.isArray,
44	    nativeKeys         = Object.keys,
45	    nativeBind         = FuncProto.bind;
46	
47	  // Create a safe reference to the Underscore object for use below.
48	  var _ = function(obj) {
49	    if (obj instanceof _) return obj;
50	    if (!(this instanceof _)) return new _(obj);
51	    this._wrapped = obj;
52	  };
53	
54	  // Export the Underscore object for **Node.js**, with
55	  // backwards-compatibility for the old `require()` API. If we're in
56	  // the browser, add `_` as a global object via a string identifier,
57	  // for Closure Compiler "advanced" mode.
58	  if (typeof exports !== 'undefined') {
59	    if (typeof module !== 'undefined' && module.exports) {
60	      exports = module.exports = _;
61	    }
62	    exports._ = _;
63	  } else {
64	    root['_'] = _;
65	  }
66	
67	  // Current version.
68	  _.VERSION = '1.4.1';
69	
70	  // Collection Functions
71	  // --------------------
72	
73	  // The cornerstone, an `each` implementation, aka `forEach`.
74	  // Handles objects with the built-in `forEach`, arrays, and raw objects.
75	  // Delegates to **ECMAScript 5**'s native `forEach` if available.
76	  var each = _.each = _.forEach = function(obj, iterator, context) {
77	    if (nativeForEach && obj.forEach === nativeForEach) {
78	      obj.forEach(iterator, context);
79	    } else if (obj.length === +obj.length) {
80	      for (var i = 0, l = obj.length; i < l; i++) {
81	        if (iterator.call(context, obj[i], i, obj) === breaker) return;
82	      }
83	    } else {
84	      for (var key in obj) {
85	        if (_.has(obj, key)) {
86	          if (iterator.call(context, obj[key], key, obj) === breaker) return;
87	        }
88	      }
89	    }
90	  };
91	
92	  // Return the results of applying the iterator to each element.
93	  // Delegates to **ECMAScript 5**'s native `map` if available.
94	  _.map = _.collect = function(obj, iterator, context) {
95	    var results = [];
96	    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
97	    each(obj, function(value, index, list) {
98	      results[results.length] = iterator.call(context, value, index, list);
99	    });
100	    return results;
101	  };
102	
103	  // **Reduce** builds up a single result from a list of values, aka `inject`,
104	  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
105	  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
106	    var initial = arguments.length > 2;
107	    if (nativeReduce && obj.reduce === nativeReduce) {
108	      if (context) iterator = _.bind(iterator, context);
109	      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
110	    }
111	    each(obj, function(value, index, list) {
112	      if (!initial) {
113	        memo = value;
114	        initial = true;
115	      } else {
116	        memo = iterator.call(context, memo, value, index, list);
117	      }
118	    });
119	    if (!initial) throw new TypeError('Reduce of empty array with no initial value');
120	    return memo;
121	  };
122	
123	  // The right-associative version of reduce, also known as `foldr`.
124	  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
125	  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
126	    var initial = arguments.length > 2;
127	    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
128	      if (context) iterator = _.bind(iterator, context);
129	      return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
130	    }
131	    var length = obj.length;
132	    if (length !== +length) {
133	      var keys = _.keys(obj);
134	      length = keys.length;
135	    }
136	    each(obj, function(value, index, list) {
137	      index = keys ? keys[--length] : --length;
138	      if (!initial) {
139	        memo = obj[index];
140	        initial = true;
141	      } else {
142	        memo = iterator.call(context, memo, obj[index], index, list);
143	      }
144	    });
145	    if (!initial) throw new TypeError('Reduce of empty array with no initial value');
146	    return memo;
147	  };
148	
149	  // Return the first value which passes a truth test. Aliased as `detect`.
150	  _.find = _.detect = function(obj, iterator, context) {
151	    var result;
152	    any(obj, function(value, index, list) {
153	      if (iterator.call(context, value, index, list)) {
154	        result = value;
155	        return true;
156	      }
157	    });
158	    return result;
159	  };
160	
161	  // Return all the elements that pass a truth test.
162	  // Delegates to **ECMAScript 5**'s native `filter` if available.
163	  // Aliased as `select`.
164	  _.filter = _.select = function(obj, iterator, context) {
165	    var results = [];
166	    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
167	    each(obj, function(value, index, list) {
168	      if (iterator.call(context, value, index, list)) results[results.length] = value;
169	    });
170	    return results;
171	  };
172	
173	  // Return all the elements for which a truth test fails.
174	  _.reject = function(obj, iterator, context) {
175	    var results = [];
176	    each(obj, function(value, index, list) {
177	      if (!iterator.call(context, value, index, list)) results[results.length] = value;
178	    });
179	    return results;
180	  };
181	
182	  // Determine whether all of the elements match a truth test.
183	  // Delegates to **ECMAScript 5**'s native `every` if available.
184	  // Aliased as `all`.
185	  _.every = _.all = function(obj, iterator, context) {
186	    iterator || (iterator = _.identity);
187	    var result = true;
188	    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
189	    each(obj, function(value, index, list) {
190	      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
191	    });
192	    return !!result;
193	  };
194	
195	  // Determine if at least one element in the object matches a truth test.
196	  // Delegates to **ECMAScript 5**'s native `some` if available.
197	  // Aliased as `any`.
198	  var any = _.some = _.any = function(obj, iterator, context) {
199	    iterator || (iterator = _.identity);
200	    var result = false;
201	    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
202	    each(obj, function(value, index, list) {
203	      if (result || (result = iterator.call(context, value, index, list))) return breaker;
204	    });
205	    return !!result;
206	  };
207	
208	  // Determine if the array or object contains a given value (using `===`).
209	  // Aliased as `include`.
210	  _.contains = _.include = function(obj, target) {
211	    var found = false;
212	    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
213	    found = any(obj, function(value) {
214	      return value === target;
215	    });
216	    return found;
217	  };
218	
219	  // Invoke a method (with arguments) on every item in a collection.
220	  _.invoke = function(obj, method) {
221	    var args = slice.call(arguments, 2);
222	    return _.map(obj, function(value) {
223	      return (_.isFunction(method) ? method : value[method]).apply(value, args);
224	    });
225	  };
226	
227	  // Convenience version of a common use case of `map`: fetching a property.
228	  _.pluck = function(obj, key) {
229	    return _.map(obj, function(value){ return value[key]; });
230	  };
231	
232	  // Convenience version of a common use case of `filter`: selecting only objects
233	  // with specific `key:value` pairs.
234	  _.where = function(obj, attrs) {
235	    if (_.isEmpty(attrs)) return [];
236	    return _.filter(obj, function(value) {
237	      for (var key in attrs) {
238	        if (attrs[key] !== value[key]) return false;
239	      }
240	      return true;
241	    });
242	  };
243	
244	  // Return the maximum element or (element-based computation).
245	  // Can't optimize arrays of integers longer than 65,535 elements.
246	  // See: https://bugs.webkit.org/show_bug.cgi?id=80797
247	  _.max = function(obj, iterator, context) {
248	    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
249	      return Math.max.apply(Math, obj);
250	    }
251	    if (!iterator && _.isEmpty(obj)) return -Infinity;
252	    var result = {computed : -Infinity};
253	    each(obj, function(value, index, list) {
254	      var computed = iterator ? iterator.call(context, value, index, list) : value;
255	      computed >= result.computed && (result = {value : value, computed : computed});
256	    });
257	    return result.value;
258	  };
259	
260	  // Return the minimum element (or element-based computation).
261	  _.min = function(obj, iterator, context) {
262	    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
263	      return Math.min.apply(Math, obj);
264	    }
265	    if (!iterator && _.isEmpty(obj)) return Infinity;
266	    var result = {computed : Infinity};
267	    each(obj, function(value, index, list) {
268	      var computed = iterator ? iterator.call(context, value, index, list) : value;
269	      computed < result.computed && (result = {value : value, computed : computed});
270	    });
271	    return result.value;
272	  };
273	
274	  // Shuffle an array.
275	  _.shuffle = function(obj) {
276	    var rand;
277	    var index = 0;
278	    var shuffled = [];
279	    each(obj, function(value) {
280	      rand = _.random(index++);
281	      shuffled[index - 1] = shuffled[rand];
282	      shuffled[rand] = value;
283	    });
284	    return shuffled;
285	  };
286	
287	  // An internal function to generate lookup iterators.
288	  var lookupIterator = function(value) {
289	    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
290	  };
291	
292	  // Sort the object's values by a criterion produced by an iterator.
293	  _.sortBy = function(obj, value, context) {
294	    var iterator = lookupIterator(value);
295	    return _.pluck(_.map(obj, function(value, index, list) {
296	      return {
297	        value : value,
298	        index : index,
299	        criteria : iterator.call(context, value, index, list)
300	      };
301	    }).sort(function(left, right) {
302	      var a = left.criteria;
303	      var b = right.criteria;
304	      if (a !== b) {
305	        if (a > b || a === void 0) return 1;
306	        if (a < b || b === void 0) return -1;
307	      }
308	      return left.index < right.index ? -1 : 1;
309	    }), 'value');
310	  };
311	
312	  // An internal function used for aggregate "group by" operations.
313	  var group = function(obj, value, context, behavior) {
314	    var result = {};
315	    var iterator = lookupIterator(value);
316	    each(obj, function(value, index) {
317	      var key = iterator.call(context, value, index, obj);
318	      behavior(result, key, value);
319	    });
320	    return result;
321	  };
322	
323	  // Groups the object's values by a criterion. Pass either a string attribute
324	  // to group by, or a function that returns the criterion.
325	  _.groupBy = function(obj, value, context) {
326	    return group(obj, value, context, function(result, key, value) {
327	      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
328	    });
329	  };
330	
331	  // Counts instances of an object that group by a certain criterion. Pass
332	  // either a string attribute to count by, or a function that returns the
333	  // criterion.
334	  _.countBy = function(obj, value, context) {
335	    return group(obj, value, context, function(result, key, value) {
336	      if (!_.has(result, key)) result[key] = 0;
337	      result[key]++;
338	    });
339	  };
340	
341	  // Use a comparator function to figure out the smallest index at which
342	  // an object should be inserted so as to maintain order. Uses binary search.
343	  _.sortedIndex = function(array, obj, iterator, context) {
344	    iterator = iterator == null ? _.identity : lookupIterator(iterator);
345	    var value = iterator.call(context, obj);
346	    var low = 0, high = array.length;
347	    while (low < high) {
348	      var mid = (low + high) >>> 1;
349	      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
350	    }
351	    return low;
352	  };
353	
354	  // Safely convert anything iterable into a real, live array.
355	  _.toArray = function(obj) {
356	    if (!obj) return [];
357	    if (obj.length === +obj.length) return slice.call(obj);
358	    return _.values(obj);
359	  };
360	
361	  // Return the number of elements in an object.
362	  _.size = function(obj) {
363	    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
364	  };
365	
366	  // Array Functions
367	  // ---------------
368	
369	  // Get the first element of an array. Passing **n** will return the first N
370	  // values in the array. Aliased as `head` and `take`. The **guard** check
371	  // allows it to work with `_.map`.
372	  _.first = _.head = _.take = function(array, n, guard) {
373	    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
374	  };
375	
376	  // Returns everything but the last entry of the array. Especially useful on
377	  // the arguments object. Passing **n** will return all the values in
378	  // the array, excluding the last N. The **guard** check allows it to work with
379	  // `_.map`.
380	  _.initial = function(array, n, guard) {
381	    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
382	  };
383	
384	  // Get the last element of an array. Passing **n** will return the last N
385	  // values in the array. The **guard** check allows it to work with `_.map`.
386	  _.last = function(array, n, guard) {
387	    if ((n != null) && !guard) {
388	      return slice.call(array, Math.max(array.length - n, 0));
389	    } else {
390	      return array[array.length - 1];
391	    }
392	  };
393	
394	  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
395	  // Especially useful on the arguments object. Passing an **n** will return
396	  // the rest N values in the array. The **guard**
397	  // check allows it to work with `_.map`.
398	  _.rest = _.tail = _.drop = function(array, n, guard) {
399	    return slice.call(array, (n == null) || guard ? 1 : n);
400	  };
401	
402	  // Trim out all falsy values from an array.
403	  _.compact = function(array) {
404	    return _.filter(array, function(value){ return !!value; });
405	  };
406	
407	  // Internal implementation of a recursive `flatten` function.
408	  var flatten = function(input, shallow, output) {
409	    each(input, function(value) {
410	      if (_.isArray(value)) {
411	        shallow ? push.apply(output, value) : flatten(value, shallow, output);
412	      } else {
413	        output.push(value);
414	      }
415	    });
416	    return output;
417	  };
418	
419	  // Return a completely flattened version of an array.
420	  _.flatten = function(array, shallow) {
421	    return flatten(array, shallow, []);
422	  };
423	
424	  // Return a version of the array that does not contain the specified value(s).
425	  _.without = function(array) {
426	    return _.difference(array, slice.call(arguments, 1));
427	  };
428	
429	  // Produce a duplicate-free version of the array. If the array has already
430	  // been sorted, you have the option of using a faster algorithm.
431	  // Aliased as `unique`.
432	  _.uniq = _.unique = function(array, isSorted, iterator, context) {
433	    var initial = iterator ? _.map(array, iterator, context) : array;
434	    var results = [];
435	    var seen = [];
436	    each(initial, function(value, index) {
437	      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
438	        seen.push(value);
439	        results.push(array[index]);
440	      }
441	    });
442	    return results;
443	  };
444	
445	  // Produce an array that contains the union: each distinct element from all of
446	  // the passed-in arrays.
447	  _.union = function() {
448	    return _.uniq(concat.apply(ArrayProto, arguments));
449	  };
450	
451	  // Produce an array that contains every item shared between all the
452	  // passed-in arrays.
453	  _.intersection = function(array) {
454	    var rest = slice.call(arguments, 1);
455	    return _.filter(_.uniq(array), function(item) {
456	      return _.every(rest, function(other) {
457	        return _.indexOf(other, item) >= 0;
458	      });
459	    });
460	  };
461	
462	  // Take the difference between one array and a number of other arrays.
463	  // Only the elements present in just the first array will remain.
464	  _.difference = function(array) {
465	    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
466	    return _.filter(array, function(value){ return !_.contains(rest, value); });
467	  };
468	
469	  // Zip together multiple lists into a single array -- elements that share
470	  // an index go together.
471	  _.zip = function() {
472	    var args = slice.call(arguments);
473	    var length = _.max(_.pluck(args, 'length'));
474	    var results = new Array(length);
475	    for (var i = 0; i < length; i++) {
476	      results[i] = _.pluck(args, "" + i);
477	    }
478	    return results;
479	  };
480	
481	  // Converts lists into objects. Pass either a single array of `[key, value]`
482	  // pairs, or two parallel arrays of the same length -- one of keys, and one of
483	  // the corresponding values.
484	  _.object = function(list, values) {
485	    var result = {};
486	    for (var i = 0, l = list.length; i < l; i++) {
487	      if (values) {
488	        result[list[i]] = values[i];
489	      } else {
490	        result[list[i][0]] = list[i][1];
491	      }
492	    }
493	    return result;
494	  };
495	
496	  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
497	  // we need this function. Return the position of the first occurrence of an
498	  // item in an array, or -1 if the item is not included in the array.
499	  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
500	  // If the array is large and already in sort order, pass `true`
501	  // for **isSorted** to use binary search.
502	  _.indexOf = function(array, item, isSorted) {
503	    var i = 0, l = array.length;
504	    if (isSorted) {
505	      if (typeof isSorted == 'number') {
506	        i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
507	      } else {
508	        i = _.sortedIndex(array, item);
509	        return array[i] === item ? i : -1;
510	      }
511	    }
512	    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
513	    for (; i < l; i++) if (array[i] === item) return i;
514	    return -1;
515	  };
516	
517	  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
518	  _.lastIndexOf = function(array, item, from) {
519	    var hasIndex = from != null;
520	    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
521	      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
522	    }
523	    var i = (hasIndex ? from : array.length);
524	    while (i--) if (array[i] === item) return i;
525	    return -1;
526	  };
527	
528	  // Generate an integer Array containing an arithmetic progression. A port of
529	  // the native Python `range()` function. See
530	  // [the Python documentation](http://docs.python.org/library/functions.html#range).
531	  _.range = function(start, stop, step) {
532	    if (arguments.length <= 1) {
533	      stop = start || 0;
534	      start = 0;
535	    }
536	    step = arguments[2] || 1;
537	
538	    var len = Math.max(Math.ceil((stop - start) / step), 0);
539	    var idx = 0;
540	    var range = new Array(len);
541	
542	    while(idx < len) {
543	      range[idx++] = start;
544	      start += step;
545	    }
546	
547	    return range;
548	  };
549	
550	  // Function (ahem) Functions
551	  // ------------------
552	
553	  // Reusable constructor function for prototype setting.
554	  var ctor = function(){};
555	
556	  // Create a function bound to a given object (assigning `this`, and arguments,
557	  // optionally). Binding with arguments is also known as `curry`.
558	  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
559	  // We check for `func.bind` first, to fail fast when `func` is undefined.
560	  _.bind = function bind(func, context) {
561	    var bound, args;
562	    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
563	    if (!_.isFunction(func)) throw new TypeError;
564	    args = slice.call(arguments, 2);
565	    return bound = function() {
566	      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
567	      ctor.prototype = func.prototype;
568	      var self = new ctor;
569	      var result = func.apply(self, args.concat(slice.call(arguments)));
570	      if (Object(result) === result) return result;
571	      return self;
572	    };
573	  };
574	
575	  // Bind all of an object's methods to that object. Useful for ensuring that
576	  // all callbacks defined on an object belong to it.
577	  _.bindAll = function(obj) {
578	    var funcs = slice.call(arguments, 1);
579	    if (funcs.length == 0) funcs = _.functions(obj);
580	    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
581	    return obj;
582	  };
583	
584	  // Memoize an expensive function by storing its results.
585	  _.memoize = function(func, hasher) {
586	    var memo = {};
587	    hasher || (hasher = _.identity);
588	    return function() {
589	      var key = hasher.apply(this, arguments);
590	      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
591	    };
592	  };
593	
594	  // Delays a function for the given number of milliseconds, and then calls
595	  // it with the arguments supplied.
596	  _.delay = function(func, wait) {
597	    var args = slice.call(arguments, 2);
598	    return setTimeout(function(){ return func.apply(null, args); }, wait);
599	  };
600	
601	  // Defers a function, scheduling it to run after the current call stack has
602	  // cleared.
603	  _.defer = function(func) {
604	    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
605	  };
606	
607	  // Returns a function, that, when invoked, will only be triggered at most once
608	  // during a given window of time.
609	  _.throttle = function(func, wait) {
610	    var context, args, timeout, throttling, more, result;
611	    var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
612	    return function() {
613	      context = this; args = arguments;
614	      var later = function() {
615	        timeout = null;
616	        if (more) {
617	          result = func.apply(context, args);
618	        }
619	        whenDone();
620	      };
621	      if (!timeout) timeout = setTimeout(later, wait);
622	      if (throttling) {
623	        more = true;
624	      } else {
625	        throttling = true;
626	        result = func.apply(context, args);
627	      }
628	      whenDone();
629	      return result;
630	    };
631	  };
632	
633	  // Returns a function, that, as long as it continues to be invoked, will not
634	  // be triggered. The function will be called after it stops being called for
635	  // N milliseconds. If `immediate` is passed, trigger the function on the
636	  // leading edge, instead of the trailing.
637	  _.debounce = function(func, wait, immediate) {
638	    var timeout, result;
639	    return function() {
640	      var context = this, args = arguments;
641	      var later = function() {
642	        timeout = null;
643	        if (!immediate) result = func.apply(context, args);
644	      };
645	      var callNow = immediate && !timeout;
646	      clearTimeout(timeout);
647	      timeout = setTimeout(later, wait);
648	      if (callNow) result = func.apply(context, args);
649	      return result;
650	    };
651	  };
652	
653	  // Returns a function that will be executed at most one time, no matter how
654	  // often you call it. Useful for lazy initialization.
655	  _.once = function(func) {
656	    var ran = false, memo;
657	    return function() {
658	      if (ran) return memo;
659	      ran = true;
660	      memo = func.apply(this, arguments);
661	      func = null;
662	      return memo;
663	    };
664	  };
665	
666	  // Returns the first function passed as an argument to the second,
667	  // allowing you to adjust arguments, run code before and after, and
668	  // conditionally execute the original function.
669	  _.wrap = function(func, wrapper) {
670	    return function() {
671	      var args = [func];
672	      push.apply(args, arguments);
673	      return wrapper.apply(this, args);
674	    };
675	  };
676	
677	  // Returns a function that is the composition of a list of functions, each
678	  // consuming the return value of the function that follows.
679	  _.compose = function() {
680	    var funcs = arguments;
681	    return function() {
682	      var args = arguments;
683	      for (var i = funcs.length - 1; i >= 0; i--) {
684	        args = [funcs[i].apply(this, args)];
685	      }
686	      return args[0];
687	    };
688	  };
689	
690	  // Returns a function that will only be executed after being called N times.
691	  _.after = function(times, func) {
692	    if (times <= 0) return func();
693	    return function() {
694	      if (--times < 1) {
695	        return func.apply(this, arguments);
696	      }
697	    };
698	  };
699	
700	  // Object Functions
701	  // ----------------
702	
703	  // Retrieve the names of an object's properties.
704	  // Delegates to **ECMAScript 5**'s native `Object.keys`
705	  _.keys = nativeKeys || function(obj) {
706	    if (obj !== Object(obj)) throw new TypeError('Invalid object');
707	    var keys = [];
708	    for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
709	    return keys;
710	  };
711	
712	  // Retrieve the values of an object's properties.
713	  _.values = function(obj) {
714	    var values = [];
715	    for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
716	    return values;
717	  };
718	
719	  // Convert an object into a list of `[key, value]` pairs.
720	  _.pairs = function(obj) {
721	    var pairs = [];
722	    for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
723	    return pairs;
724	  };
725	
726	  // Invert the keys and values of an object. The values must be serializable.
727	  _.invert = function(obj) {
728	    var result = {};
729	    for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
730	    return result;
731	  };
732	
733	  // Return a sorted list of the function names available on the object.
734	  // Aliased as `methods`
735	  _.functions = _.methods = function(obj) {
736	    var names = [];
737	    for (var key in obj) {
738	      if (_.isFunction(obj[key])) names.push(key);
739	    }
740	    return names.sort();
741	  };
742	
743	  // Extend a given object with all the properties in passed-in object(s).
744	  _.extend = function(obj) {
745	    each(slice.call(arguments, 1), function(source) {
746	      for (var prop in source) {
747	        obj[prop] = source[prop];
748	      }
749	    });
750	    return obj;
751	  };
752	
753	  // Return a copy of the object only containing the whitelisted properties.
754	  _.pick = function(obj) {
755	    var copy = {};
756	    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
757	    each(keys, function(key) {
758	      if (key in obj) copy[key] = obj[key];
759	    });
760	    return copy;
761	  };
762	
763	   // Return a copy of the object without the blacklisted properties.
764	  _.omit = function(obj) {
765	    var copy = {};
766	    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
767	    for (var key in obj) {
768	      if (!_.contains(keys, key)) copy[key] = obj[key];
769	    }
770	    return copy;
771	  };
772	
773	  // Fill in a given object with default properties.
774	  _.defaults = function(obj) {
775	    each(slice.call(arguments, 1), function(source) {
776	      for (var prop in source) {
777	        if (obj[prop] == null) obj[prop] = source[prop];
778	      }
779	    });
780	    return obj;
781	  };
782	
783	  // Create a (shallow-cloned) duplicate of an object.
784	  _.clone = function(obj) {
785	    if (!_.isObject(obj)) return obj;
786	    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
787	  };
788	
789	  // Invokes interceptor with the obj, and then returns obj.
790	  // The primary purpose of this method is to "tap into" a method chain, in
791	  // order to perform operations on intermediate results within the chain.
792	  _.tap = function(obj, interceptor) {
793	    interceptor(obj);
794	    return obj;
795	  };
796	
797	  // Internal recursive comparison function for `isEqual`.
798	  var eq = function(a, b, aStack, bStack) {
799	    // Identical objects are equal. `0 === -0`, but they aren't identical.
800	    // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
801	    if (a === b) return a !== 0 || 1 / a == 1 / b;
802	    // A strict comparison is necessary because `null == undefined`.
803	    if (a == null || b == null) return a === b;
804	    // Unwrap any wrapped objects.
805	    if (a instanceof _) a = a._wrapped;
806	    if (b instanceof _) b = b._wrapped;
807	    // Compare `[[Class]]` names.
808	    var className = toString.call(a);
809	    if (className != toString.call(b)) return false;
810	    switch (className) {
811	      // Strings, numbers, dates, and booleans are compared by value.
812	      case '[object String]':
813	        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
814	        // equivalent to `new String("5")`.
815	        return a == String(b);
816	      case '[object Number]':
817	        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
818	        // other numeric values.
819	        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
820	      case '[object Date]':
821	      case '[object Boolean]':
822	        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
823	        // millisecond representations. Note that invalid dates with millisecond representations
824	        // of `NaN` are not equivalent.
825	        return +a == +b;
826	      // RegExps are compared by their source patterns and flags.
827	      case '[object RegExp]':
828	        return a.source == b.source &&
829	               a.global == b.global &&
830	               a.multiline == b.multiline &&
831	               a.ignoreCase == b.ignoreCase;
832	    }
833	    if (typeof a != 'object' || typeof b != 'object') return false;
834	    // Assume equality for cyclic structures. The algorithm for detecting cyclic
835	    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
836	    var length = aStack.length;
837	    while (length--) {
838	      // Linear search. Performance is inversely proportional to the number of
839	      // unique nested structures.
840	      if (aStack[length] == a) return bStack[length] == b;
841	    }
842	    // Add the first object to the stack of traversed objects.
843	    aStack.push(a);
844	    bStack.push(b);
845	    var size = 0, result = true;
846	    // Recursively compare objects and arrays.
847	    if (className == '[object Array]') {
848	      // Compare array lengths to determine if a deep comparison is necessary.
849	      size = a.length;
850	      result = size == b.length;
851	      if (result) {
852	        // Deep compare the contents, ignoring non-numeric properties.
853	        while (size--) {
854	          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
855	        }
856	      }
857	    } else {
858	      // Objects with different constructors are not equivalent, but `Object`s
859	      // from different frames are.
860	      var aCtor = a.constructor, bCtor = b.constructor;
861	      if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
862	                               _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
863	        return false;
864	      }
865	      // Deep compare objects.
866	      for (var key in a) {
867	        if (_.has(a, key)) {
868	          // Count the expected number of properties.
869	          size++;
870	          // Deep compare each member.
871	          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
872	        }
873	      }
874	      // Ensure that both objects contain the same number of properties.
875	      if (result) {
876	        for (key in b) {
877	          if (_.has(b, key) && !(size--)) break;
878	        }
879	        result = !size;
880	      }
881	    }
882	    // Remove the first object from the stack of traversed objects.
883	    aStack.pop();
884	    bStack.pop();
885	    return result;
886	  };
887	
888	  // Perform a deep comparison to check if two objects are equal.
889	  _.isEqual = function(a, b) {
890	    return eq(a, b, [], []);
891	  };
892	
893	  // Is a given array, string, or object empty?
894	  // An "empty" object has no enumerable own-properties.
895	  _.isEmpty = function(obj) {
896	    if (obj == null) return true;
897	    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
898	    for (var key in obj) if (_.has(obj, key)) return false;
899	    return true;
900	  };
901	
902	  // Is a given value a DOM element?
903	  _.isElement = function(obj) {
904	    return !!(obj && obj.nodeType === 1);
905	  };
906	
907	  // Is a given value an array?
908	  // Delegates to ECMA5's native Array.isArray
909	  _.isArray = nativeIsArray || function(obj) {
910	    return toString.call(obj) == '[object Array]';
911	  };
912	
913	  // Is a given variable an object?
914	  _.isObject = function(obj) {
915	    return obj === Object(obj);
916	  };
917	
918	  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
919	  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
920	    _['is' + name] = function(obj) {
921	      return toString.call(obj) == '[object ' + name + ']';
922	    };
923	  });
924	
925	  // Define a fallback version of the method in browsers (ahem, IE), where
926	  // there isn't any inspectable "Arguments" type.
927	  if (!_.isArguments(arguments)) {
928	    _.isArguments = function(obj) {
929	      return !!(obj && _.has(obj, 'callee'));
930	    };
931	  }
932	
933	  // Optimize `isFunction` if appropriate.
934	  if (typeof (/./) !== 'function') {
935	    _.isFunction = function(obj) {
936	      return typeof obj === 'function';
937	    };
938	  }
939	
940	  // Is a given object a finite number?
941	  _.isFinite = function(obj) {
942	    return _.isNumber(obj) && isFinite(obj);
943	  };
944	
945	  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
946	  _.isNaN = function(obj) {
947	    return _.isNumber(obj) && obj != +obj;
948	  };
949	
950	  // Is a given value a boolean?
951	  _.isBoolean = function(obj) {
952	    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
953	  };
954	
955	  // Is a given value equal to null?
956	  _.isNull = function(obj) {
957	    return obj === null;
958	  };
959	
960	  // Is a given variable undefined?
961	  _.isUndefined = function(obj) {
962	    return obj === void 0;
963	  };
964	
965	  // Shortcut function for checking if an object has a given property directly
966	  // on itself (in other words, not on a prototype).
967	  _.has = function(obj, key) {
968	    return hasOwnProperty.call(obj, key);
969	  };
970	
971	  // Utility Functions
972	  // -----------------
973	
974	  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
975	  // previous owner. Returns a reference to the Underscore object.
976	  _.noConflict = function() {
977	    root._ = previousUnderscore;
978	    return this;
979	  };
980	
981	  // Keep the identity function around for default iterators.
982	  _.identity = function(value) {
983	    return value;
984	  };
985	
986	  // Run a function **n** times.
987	  _.times = function(n, iterator, context) {
988	    for (var i = 0; i < n; i++) iterator.call(context, i);
989	  };
990	
991	  // Return a random integer between min and max (inclusive).
992	  _.random = function(min, max) {
993	    if (max == null) {
994	      max = min;
995	      min = 0;
996	    }
997	    return min + (0 | Math.random() * (max - min + 1));
998	  };
999	
1000	  // List of HTML entities for escaping.
1001	  var entityMap = {
1002	    escape: {
1003	      '&': '&amp;',
1004	      '<': '&lt;',
1005	      '>': '&gt;',
1006	      '"': '&quot;',
1007	      "'": '&#x27;',
1008	      '/': '&#x2F;'
1009	    }
1010	  };
1011	  entityMap.unescape = _.invert(entityMap.escape);
1012	
1013	  // Regexes containing the keys and values listed immediately above.
1014	  var entityRegexes = {
1015	    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
1016	    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
1017	  };
1018	
1019	  // Functions for escaping and unescaping strings to/from HTML interpolation.
1020	  _.each(['escape', 'unescape'], function(method) {
1021	    _[method] = function(string) {
1022	      if (string == null) return '';
1023	      return ('' + string).replace(entityRegexes[method], function(match) {
1024	        return entityMap[method][match];
1025	      });
1026	    };
1027	  });
1028	
1029	  // If the value of the named property is a function then invoke it;
1030	  // otherwise, return it.
1031	  _.result = function(object, property) {
1032	    if (object == null) return null;
1033	    var value = object[property];
1034	    return _.isFunction(value) ? value.call(object) : value;
1035	  };
1036	
1037	  // Add your own custom functions to the Underscore object.
1038	  _.mixin = function(obj) {
1039	    each(_.functions(obj), function(name){
1040	      var func = _[name] = obj[name];
1041	      _.prototype[name] = function() {
1042	        var args = [this._wrapped];
1043	        push.apply(args, arguments);
1044	        return result.call(this, func.apply(_, args));
1045	      };
1046	    });
1047	  };
1048	
1049	  // Generate a unique integer id (unique within the entire client session).
1050	  // Useful for temporary DOM ids.
1051	  var idCounter = 0;
1052	  _.uniqueId = function(prefix) {
1053	    var id = idCounter++;
1054	    return prefix ? prefix + id : id;
1055	  };
1056	
1057	  // By default, Underscore uses ERB-style template delimiters, change the
1058	  // following template settings to use alternative delimiters.
1059	  _.templateSettings = {
1060	    evaluate    : /<%([\s\S]+?)%>/g,
1061	    interpolate : /<%=([\s\S]+?)%>/g,
1062	    escape      : /<%-([\s\S]+?)%>/g
1063	  };
1064	
1065	  // When customizing `templateSettings`, if you don't want to define an
1066	  // interpolation, evaluation or escaping regex, we need one that is
1067	  // guaranteed not to match.
1068	  var noMatch = /(.)^/;
1069	
1070	  // Certain characters need to be escaped so that they can be put into a
1071	  // string literal.
1072	  var escapes = {
1073	    "'":      "'",
1074	    '\\':     '\\',
1075	    '\r':     'r',
1076	    '\n':     'n',
1077	    '\t':     't',
1078	    '\u2028': 'u2028',
1079	    '\u2029': 'u2029'
1080	  };
1081	
1082	  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
1083	
1084	  // JavaScript micro-templating, similar to John Resig's implementation.
1085	  // Underscore templating handles arbitrary delimiters, preserves whitespace,
1086	  // and correctly escapes quotes within interpolated code.
1087	  _.template = function(text, data, settings) {
1088	    settings = _.defaults({}, settings, _.templateSettings);
1089	
1090	    // Combine delimiters into one regular expression via alternation.
1091	    var matcher = new RegExp([
1092	      (settings.escape || noMatch).source,
1093	      (settings.interpolate || noMatch).source,
1094	      (settings.evaluate || noMatch).source
1095	    ].join('|') + '|$', 'g');
1096	
1097	    // Compile the template source, escaping string literals appropriately.
1098	    var index = 0;
1099	    var source = "__p+='";
1100	    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
1101	      source += text.slice(index, offset)
1102	        .replace(escaper, function(match) { return '\\' + escapes[match]; });
1103	      source +=
1104	        escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
1105	        interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
1106	        evaluate ? "';\n" + evaluate + "\n__p+='" : '';
1107	      index = offset + match.length;
1108	    });
1109	    source += "';\n";
1110	
1111	    // If a variable is not specified, place data values in local scope.
1112	    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
1113	
1114	    source = "var __t,__p='',__j=Array.prototype.join," +
1115	      "print=function(){__p+=__j.call(arguments,'');};\n" +
1116	      source + "return __p;\n";
1117	
1118	    try {
1119	      var render = new Function(settings.variable || 'obj', '_', source);
1120	    } catch (e) {
1121	      e.source = source;
1122	      throw e;
1123	    }
1124	
1125	    if (data) return render(data, _);
1126	    var template = function(data) {
1127	      return render.call(this, data, _);
1128	    };
1129	
1130	    // Provide the compiled function source as a convenience for precompilation.
1131	    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
1132	
1133	    return template;
1134	  };
1135	
1136	  // Add a "chain" function, which will delegate to the wrapper.
1137	  _.chain = function(obj) {
1138	    return _(obj).chain();
1139	  };
1140	
1141	  // OOP
1142	  // ---------------
1143	  // If Underscore is called as a function, it returns a wrapped object that
1144	  // can be used OO-style. This wrapper holds altered versions of all the
1145	  // underscore functions. Wrapped objects may be chained.
1146	
1147	  // Helper function to continue chaining intermediate results.
1148	  var result = function(obj) {
1149	    return this._chain ? _(obj).chain() : obj;
1150	  };
1151	
1152	  // Add all of the Underscore functions to the wrapper object.
1153	  _.mixin(_);
1154	
1155	  // Add all mutator Array functions to the wrapper.
1156	  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
1157	    var method = ArrayProto[name];
1158	    _.prototype[name] = function() {
1159	      var obj = this._wrapped;
1160	      method.apply(obj, arguments);
1161	      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
1162	      return result.call(this, obj);
1163	    };
1164	  });
1165	
1166	  // Add all accessor Array functions to the wrapper.
1167	  each(['concat', 'join', 'slice'], function(name) {
1168	    var method = ArrayProto[name];
1169	    _.prototype[name] = function() {
1170	      return result.call(this, method.apply(this._wrapped, arguments));
1171	    };
1172	  });
1173	
1174	  _.extend(_.prototype, {
1175	
1176	    // Start chaining a wrapped Underscore object.
1177	    chain: function() {
1178	      this._chain = true;
1179	      return this;
1180	    },
1181	
1182	    // Extracts the result from a wrapped and chained object.
1183	    value: function() {
1184	      return this._wrapped;
1185	    }
1186	
1187	  });
1188	
1189	}).call(this);

Contact Us
Can't read the article? Contact us for a free answer! Free help for personal, small business sites!
Tel: 020-2206-9892
QQ咨询:1025174874
(iii) E-mail: info@361sale.com
Working hours: Monday to Friday, 9:30-18:30, holidays off
Posted by photon fluctuations, retweeted with attribution:https://www.361sale.com/en/11656/

Like (1)
Previous June 19, 2024 at 10:59 am
Next June 19, 2024 am11:18

Recommended

Leave a Reply

Your email address will not be published. Required fields are marked *

Contact Us

020-2206-9892

QQ咨询:1025174874

E-mail: info@361sale.com

Working hours: Monday to Friday, 9:30-18:30, holidays off

Customer Service
In order to facilitate global user registration and login, we have canceled the telephone login function. If you encounter login problems, please contact our customer service for assistance in binding your email address.