underscore-rails 1.5.2 → 1.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/underscore-rails/version.rb +1 -1
- data/vendor/assets/javascripts/underscore.js +823 -551
- metadata +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Underscore.js 1.
|
|
1
|
+
// Underscore.js 1.8.3
|
|
2
2
|
// http://underscorejs.org
|
|
3
|
-
// (c) 2009-
|
|
3
|
+
// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
|
4
4
|
// Underscore may be freely distributed under the MIT license.
|
|
5
5
|
|
|
6
6
|
(function() {
|
|
@@ -14,9 +14,6 @@
|
|
|
14
14
|
// Save the previous value of the `_` variable.
|
|
15
15
|
var previousUnderscore = root._;
|
|
16
16
|
|
|
17
|
-
// Establish the object that gets returned to break out of a loop iteration.
|
|
18
|
-
var breaker = {};
|
|
19
|
-
|
|
20
17
|
// Save bytes in the minified (but not gzipped) version:
|
|
21
18
|
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
|
22
19
|
|
|
@@ -24,25 +21,19 @@
|
|
|
24
21
|
var
|
|
25
22
|
push = ArrayProto.push,
|
|
26
23
|
slice = ArrayProto.slice,
|
|
27
|
-
concat = ArrayProto.concat,
|
|
28
24
|
toString = ObjProto.toString,
|
|
29
25
|
hasOwnProperty = ObjProto.hasOwnProperty;
|
|
30
26
|
|
|
31
27
|
// All **ECMAScript 5** native function implementations that we hope to use
|
|
32
28
|
// are declared here.
|
|
33
29
|
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
30
|
nativeIsArray = Array.isArray,
|
|
44
31
|
nativeKeys = Object.keys,
|
|
45
|
-
nativeBind = FuncProto.bind
|
|
32
|
+
nativeBind = FuncProto.bind,
|
|
33
|
+
nativeCreate = Object.create;
|
|
34
|
+
|
|
35
|
+
// Naked function reference for surrogate-prototype-swapping.
|
|
36
|
+
var Ctor = function(){};
|
|
46
37
|
|
|
47
38
|
// Create a safe reference to the Underscore object for use below.
|
|
48
39
|
var _ = function(obj) {
|
|
@@ -53,8 +44,7 @@
|
|
|
53
44
|
|
|
54
45
|
// Export the Underscore object for **Node.js**, with
|
|
55
46
|
// backwards-compatibility for the old `require()` API. If we're in
|
|
56
|
-
// the browser, add `_` as a global object
|
|
57
|
-
// for Closure Compiler "advanced" mode.
|
|
47
|
+
// the browser, add `_` as a global object.
|
|
58
48
|
if (typeof exports !== 'undefined') {
|
|
59
49
|
if (typeof module !== 'undefined' && module.exports) {
|
|
60
50
|
exports = module.exports = _;
|
|
@@ -65,160 +55,217 @@
|
|
|
65
55
|
}
|
|
66
56
|
|
|
67
57
|
// Current version.
|
|
68
|
-
_.VERSION = '1.
|
|
58
|
+
_.VERSION = '1.8.3';
|
|
59
|
+
|
|
60
|
+
// Internal function that returns an efficient (for current engines) version
|
|
61
|
+
// of the passed-in callback, to be repeatedly applied in other Underscore
|
|
62
|
+
// functions.
|
|
63
|
+
var optimizeCb = function(func, context, argCount) {
|
|
64
|
+
if (context === void 0) return func;
|
|
65
|
+
switch (argCount == null ? 3 : argCount) {
|
|
66
|
+
case 1: return function(value) {
|
|
67
|
+
return func.call(context, value);
|
|
68
|
+
};
|
|
69
|
+
case 2: return function(value, other) {
|
|
70
|
+
return func.call(context, value, other);
|
|
71
|
+
};
|
|
72
|
+
case 3: return function(value, index, collection) {
|
|
73
|
+
return func.call(context, value, index, collection);
|
|
74
|
+
};
|
|
75
|
+
case 4: return function(accumulator, value, index, collection) {
|
|
76
|
+
return func.call(context, accumulator, value, index, collection);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return function() {
|
|
80
|
+
return func.apply(context, arguments);
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// A mostly-internal function to generate callbacks that can be applied
|
|
85
|
+
// to each element in a collection, returning the desired result — either
|
|
86
|
+
// identity, an arbitrary callback, a property matcher, or a property accessor.
|
|
87
|
+
var cb = function(value, context, argCount) {
|
|
88
|
+
if (value == null) return _.identity;
|
|
89
|
+
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
|
|
90
|
+
if (_.isObject(value)) return _.matcher(value);
|
|
91
|
+
return _.property(value);
|
|
92
|
+
};
|
|
93
|
+
_.iteratee = function(value, context) {
|
|
94
|
+
return cb(value, context, Infinity);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// An internal function for creating assigner functions.
|
|
98
|
+
var createAssigner = function(keysFunc, undefinedOnly) {
|
|
99
|
+
return function(obj) {
|
|
100
|
+
var length = arguments.length;
|
|
101
|
+
if (length < 2 || obj == null) return obj;
|
|
102
|
+
for (var index = 1; index < length; index++) {
|
|
103
|
+
var source = arguments[index],
|
|
104
|
+
keys = keysFunc(source),
|
|
105
|
+
l = keys.length;
|
|
106
|
+
for (var i = 0; i < l; i++) {
|
|
107
|
+
var key = keys[i];
|
|
108
|
+
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return obj;
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// An internal function for creating a new object that inherits from another.
|
|
116
|
+
var baseCreate = function(prototype) {
|
|
117
|
+
if (!_.isObject(prototype)) return {};
|
|
118
|
+
if (nativeCreate) return nativeCreate(prototype);
|
|
119
|
+
Ctor.prototype = prototype;
|
|
120
|
+
var result = new Ctor;
|
|
121
|
+
Ctor.prototype = null;
|
|
122
|
+
return result;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
var property = function(key) {
|
|
126
|
+
return function(obj) {
|
|
127
|
+
return obj == null ? void 0 : obj[key];
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// Helper for collection methods to determine whether a collection
|
|
132
|
+
// should be iterated as an array or as an object
|
|
133
|
+
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
|
|
134
|
+
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
|
|
135
|
+
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
|
|
136
|
+
var getLength = property('length');
|
|
137
|
+
var isArrayLike = function(collection) {
|
|
138
|
+
var length = getLength(collection);
|
|
139
|
+
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
|
|
140
|
+
};
|
|
69
141
|
|
|
70
142
|
// Collection Functions
|
|
71
143
|
// --------------------
|
|
72
144
|
|
|
73
145
|
// The cornerstone, an `each` implementation, aka `forEach`.
|
|
74
|
-
// Handles objects
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (iterator.call(context, obj[i], i, obj) === breaker) return;
|
|
146
|
+
// Handles raw objects in addition to array-likes. Treats all
|
|
147
|
+
// sparse array-likes as if they were dense.
|
|
148
|
+
_.each = _.forEach = function(obj, iteratee, context) {
|
|
149
|
+
iteratee = optimizeCb(iteratee, context);
|
|
150
|
+
var i, length;
|
|
151
|
+
if (isArrayLike(obj)) {
|
|
152
|
+
for (i = 0, length = obj.length; i < length; i++) {
|
|
153
|
+
iteratee(obj[i], i, obj);
|
|
83
154
|
}
|
|
84
155
|
} else {
|
|
85
156
|
var keys = _.keys(obj);
|
|
86
|
-
for (
|
|
87
|
-
|
|
157
|
+
for (i = 0, length = keys.length; i < length; i++) {
|
|
158
|
+
iteratee(obj[keys[i]], keys[i], obj);
|
|
88
159
|
}
|
|
89
160
|
}
|
|
161
|
+
return obj;
|
|
90
162
|
};
|
|
91
163
|
|
|
92
|
-
// Return the results of applying the
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
var
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
164
|
+
// Return the results of applying the iteratee to each element.
|
|
165
|
+
_.map = _.collect = function(obj, iteratee, context) {
|
|
166
|
+
iteratee = cb(iteratee, context);
|
|
167
|
+
var keys = !isArrayLike(obj) && _.keys(obj),
|
|
168
|
+
length = (keys || obj).length,
|
|
169
|
+
results = Array(length);
|
|
170
|
+
for (var index = 0; index < length; index++) {
|
|
171
|
+
var currentKey = keys ? keys[index] : index;
|
|
172
|
+
results[index] = iteratee(obj[currentKey], currentKey, obj);
|
|
173
|
+
}
|
|
101
174
|
return results;
|
|
102
175
|
};
|
|
103
176
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return
|
|
177
|
+
// Create a reducing function iterating left or right.
|
|
178
|
+
function createReduce(dir) {
|
|
179
|
+
// Optimized iterator function as using arguments.length
|
|
180
|
+
// in the main function will deoptimize the, see #1991.
|
|
181
|
+
function iterator(obj, iteratee, memo, keys, index, length) {
|
|
182
|
+
for (; index >= 0 && index < length; index += dir) {
|
|
183
|
+
var currentKey = keys ? keys[index] : index;
|
|
184
|
+
memo = iteratee(memo, obj[currentKey], currentKey, obj);
|
|
185
|
+
}
|
|
186
|
+
return memo;
|
|
114
187
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
188
|
+
|
|
189
|
+
return function(obj, iteratee, memo, context) {
|
|
190
|
+
iteratee = optimizeCb(iteratee, context, 4);
|
|
191
|
+
var keys = !isArrayLike(obj) && _.keys(obj),
|
|
192
|
+
length = (keys || obj).length,
|
|
193
|
+
index = dir > 0 ? 0 : length - 1;
|
|
194
|
+
// Determine the initial value if none is provided.
|
|
195
|
+
if (arguments.length < 3) {
|
|
196
|
+
memo = obj[keys ? keys[index] : index];
|
|
197
|
+
index += dir;
|
|
121
198
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
199
|
+
return iterator(obj, iteratee, memo, keys, index, length);
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
|
204
|
+
// or `foldl`.
|
|
205
|
+
_.reduce = _.foldl = _.inject = createReduce(1);
|
|
126
206
|
|
|
127
207
|
// The right-associative version of reduce, also known as `foldr`.
|
|
128
|
-
|
|
129
|
-
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
|
130
|
-
var initial = arguments.length > 2;
|
|
131
|
-
if (obj == null) obj = [];
|
|
132
|
-
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
|
133
|
-
if (context) iterator = _.bind(iterator, context);
|
|
134
|
-
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
|
135
|
-
}
|
|
136
|
-
var length = obj.length;
|
|
137
|
-
if (length !== +length) {
|
|
138
|
-
var keys = _.keys(obj);
|
|
139
|
-
length = keys.length;
|
|
140
|
-
}
|
|
141
|
-
each(obj, function(value, index, list) {
|
|
142
|
-
index = keys ? keys[--length] : --length;
|
|
143
|
-
if (!initial) {
|
|
144
|
-
memo = obj[index];
|
|
145
|
-
initial = true;
|
|
146
|
-
} else {
|
|
147
|
-
memo = iterator.call(context, memo, obj[index], index, list);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
if (!initial) throw new TypeError(reduceError);
|
|
151
|
-
return memo;
|
|
152
|
-
};
|
|
208
|
+
_.reduceRight = _.foldr = createReduce(-1);
|
|
153
209
|
|
|
154
210
|
// Return the first value which passes a truth test. Aliased as `detect`.
|
|
155
|
-
_.find = _.detect = function(obj,
|
|
156
|
-
var
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return result;
|
|
211
|
+
_.find = _.detect = function(obj, predicate, context) {
|
|
212
|
+
var key;
|
|
213
|
+
if (isArrayLike(obj)) {
|
|
214
|
+
key = _.findIndex(obj, predicate, context);
|
|
215
|
+
} else {
|
|
216
|
+
key = _.findKey(obj, predicate, context);
|
|
217
|
+
}
|
|
218
|
+
if (key !== void 0 && key !== -1) return obj[key];
|
|
164
219
|
};
|
|
165
220
|
|
|
166
221
|
// Return all the elements that pass a truth test.
|
|
167
|
-
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
|
168
222
|
// Aliased as `select`.
|
|
169
|
-
_.filter = _.select = function(obj,
|
|
223
|
+
_.filter = _.select = function(obj, predicate, context) {
|
|
170
224
|
var results = [];
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (iterator.call(context, value, index, list)) results.push(value);
|
|
225
|
+
predicate = cb(predicate, context);
|
|
226
|
+
_.each(obj, function(value, index, list) {
|
|
227
|
+
if (predicate(value, index, list)) results.push(value);
|
|
175
228
|
});
|
|
176
229
|
return results;
|
|
177
230
|
};
|
|
178
231
|
|
|
179
232
|
// Return all the elements for which a truth test fails.
|
|
180
|
-
_.reject = function(obj,
|
|
181
|
-
return _.filter(obj,
|
|
182
|
-
return !iterator.call(context, value, index, list);
|
|
183
|
-
}, context);
|
|
233
|
+
_.reject = function(obj, predicate, context) {
|
|
234
|
+
return _.filter(obj, _.negate(cb(predicate)), context);
|
|
184
235
|
};
|
|
185
236
|
|
|
186
237
|
// Determine whether all of the elements match a truth test.
|
|
187
|
-
// Delegates to **ECMAScript 5**'s native `every` if available.
|
|
188
238
|
// Aliased as `all`.
|
|
189
|
-
_.every = _.all = function(obj,
|
|
190
|
-
|
|
191
|
-
var
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
if (!(
|
|
196
|
-
}
|
|
197
|
-
return
|
|
239
|
+
_.every = _.all = function(obj, predicate, context) {
|
|
240
|
+
predicate = cb(predicate, context);
|
|
241
|
+
var keys = !isArrayLike(obj) && _.keys(obj),
|
|
242
|
+
length = (keys || obj).length;
|
|
243
|
+
for (var index = 0; index < length; index++) {
|
|
244
|
+
var currentKey = keys ? keys[index] : index;
|
|
245
|
+
if (!predicate(obj[currentKey], currentKey, obj)) return false;
|
|
246
|
+
}
|
|
247
|
+
return true;
|
|
198
248
|
};
|
|
199
249
|
|
|
200
250
|
// Determine if at least one element in the object matches a truth test.
|
|
201
|
-
// Delegates to **ECMAScript 5**'s native `some` if available.
|
|
202
251
|
// Aliased as `any`.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
var
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (
|
|
210
|
-
}
|
|
211
|
-
return
|
|
252
|
+
_.some = _.any = function(obj, predicate, context) {
|
|
253
|
+
predicate = cb(predicate, context);
|
|
254
|
+
var keys = !isArrayLike(obj) && _.keys(obj),
|
|
255
|
+
length = (keys || obj).length;
|
|
256
|
+
for (var index = 0; index < length; index++) {
|
|
257
|
+
var currentKey = keys ? keys[index] : index;
|
|
258
|
+
if (predicate(obj[currentKey], currentKey, obj)) return true;
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
212
261
|
};
|
|
213
262
|
|
|
214
|
-
// Determine if the array or object contains a given
|
|
215
|
-
// Aliased as `include`.
|
|
216
|
-
_.contains = _.include = function(obj,
|
|
217
|
-
if (obj
|
|
218
|
-
if (
|
|
219
|
-
return
|
|
220
|
-
return value === target;
|
|
221
|
-
});
|
|
263
|
+
// Determine if the array or object contains a given item (using `===`).
|
|
264
|
+
// Aliased as `includes` and `include`.
|
|
265
|
+
_.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
|
|
266
|
+
if (!isArrayLike(obj)) obj = _.values(obj);
|
|
267
|
+
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
|
|
268
|
+
return _.indexOf(obj, item, fromIndex) >= 0;
|
|
222
269
|
};
|
|
223
270
|
|
|
224
271
|
// Invoke a method (with arguments) on every item in a collection.
|
|
@@ -226,100 +273,111 @@
|
|
|
226
273
|
var args = slice.call(arguments, 2);
|
|
227
274
|
var isFunc = _.isFunction(method);
|
|
228
275
|
return _.map(obj, function(value) {
|
|
229
|
-
|
|
276
|
+
var func = isFunc ? method : value[method];
|
|
277
|
+
return func == null ? func : func.apply(value, args);
|
|
230
278
|
});
|
|
231
279
|
};
|
|
232
280
|
|
|
233
281
|
// Convenience version of a common use case of `map`: fetching a property.
|
|
234
282
|
_.pluck = function(obj, key) {
|
|
235
|
-
return _.map(obj,
|
|
283
|
+
return _.map(obj, _.property(key));
|
|
236
284
|
};
|
|
237
285
|
|
|
238
286
|
// Convenience version of a common use case of `filter`: selecting only objects
|
|
239
287
|
// containing specific `key:value` pairs.
|
|
240
|
-
_.where = function(obj, attrs
|
|
241
|
-
|
|
242
|
-
return _[first ? 'find' : 'filter'](obj, function(value) {
|
|
243
|
-
for (var key in attrs) {
|
|
244
|
-
if (attrs[key] !== value[key]) return false;
|
|
245
|
-
}
|
|
246
|
-
return true;
|
|
247
|
-
});
|
|
288
|
+
_.where = function(obj, attrs) {
|
|
289
|
+
return _.filter(obj, _.matcher(attrs));
|
|
248
290
|
};
|
|
249
291
|
|
|
250
292
|
// Convenience version of a common use case of `find`: getting the first object
|
|
251
293
|
// containing specific `key:value` pairs.
|
|
252
294
|
_.findWhere = function(obj, attrs) {
|
|
253
|
-
return _.
|
|
295
|
+
return _.find(obj, _.matcher(attrs));
|
|
254
296
|
};
|
|
255
297
|
|
|
256
|
-
// Return the maximum element or
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (
|
|
261
|
-
|
|
298
|
+
// Return the maximum element (or element-based computation).
|
|
299
|
+
_.max = function(obj, iteratee, context) {
|
|
300
|
+
var result = -Infinity, lastComputed = -Infinity,
|
|
301
|
+
value, computed;
|
|
302
|
+
if (iteratee == null && obj != null) {
|
|
303
|
+
obj = isArrayLike(obj) ? obj : _.values(obj);
|
|
304
|
+
for (var i = 0, length = obj.length; i < length; i++) {
|
|
305
|
+
value = obj[i];
|
|
306
|
+
if (value > result) {
|
|
307
|
+
result = value;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
} else {
|
|
311
|
+
iteratee = cb(iteratee, context);
|
|
312
|
+
_.each(obj, function(value, index, list) {
|
|
313
|
+
computed = iteratee(value, index, list);
|
|
314
|
+
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
|
|
315
|
+
result = value;
|
|
316
|
+
lastComputed = computed;
|
|
317
|
+
}
|
|
318
|
+
});
|
|
262
319
|
}
|
|
263
|
-
|
|
264
|
-
var result = {computed : -Infinity, value: -Infinity};
|
|
265
|
-
each(obj, function(value, index, list) {
|
|
266
|
-
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
|
267
|
-
computed > result.computed && (result = {value : value, computed : computed});
|
|
268
|
-
});
|
|
269
|
-
return result.value;
|
|
320
|
+
return result;
|
|
270
321
|
};
|
|
271
322
|
|
|
272
323
|
// Return the minimum element (or element-based computation).
|
|
273
|
-
_.min = function(obj,
|
|
274
|
-
|
|
275
|
-
|
|
324
|
+
_.min = function(obj, iteratee, context) {
|
|
325
|
+
var result = Infinity, lastComputed = Infinity,
|
|
326
|
+
value, computed;
|
|
327
|
+
if (iteratee == null && obj != null) {
|
|
328
|
+
obj = isArrayLike(obj) ? obj : _.values(obj);
|
|
329
|
+
for (var i = 0, length = obj.length; i < length; i++) {
|
|
330
|
+
value = obj[i];
|
|
331
|
+
if (value < result) {
|
|
332
|
+
result = value;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
iteratee = cb(iteratee, context);
|
|
337
|
+
_.each(obj, function(value, index, list) {
|
|
338
|
+
computed = iteratee(value, index, list);
|
|
339
|
+
if (computed < lastComputed || computed === Infinity && result === Infinity) {
|
|
340
|
+
result = value;
|
|
341
|
+
lastComputed = computed;
|
|
342
|
+
}
|
|
343
|
+
});
|
|
276
344
|
}
|
|
277
|
-
|
|
278
|
-
var result = {computed : Infinity, value: Infinity};
|
|
279
|
-
each(obj, function(value, index, list) {
|
|
280
|
-
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
|
281
|
-
computed < result.computed && (result = {value : value, computed : computed});
|
|
282
|
-
});
|
|
283
|
-
return result.value;
|
|
345
|
+
return result;
|
|
284
346
|
};
|
|
285
347
|
|
|
286
|
-
// Shuffle
|
|
287
|
-
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher
|
|
348
|
+
// Shuffle a collection, using the modern version of the
|
|
349
|
+
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
|
288
350
|
_.shuffle = function(obj) {
|
|
289
|
-
var
|
|
290
|
-
var
|
|
291
|
-
var shuffled =
|
|
292
|
-
|
|
293
|
-
rand = _.random(index
|
|
294
|
-
shuffled[index
|
|
295
|
-
shuffled[rand] =
|
|
296
|
-
}
|
|
351
|
+
var set = isArrayLike(obj) ? obj : _.values(obj);
|
|
352
|
+
var length = set.length;
|
|
353
|
+
var shuffled = Array(length);
|
|
354
|
+
for (var index = 0, rand; index < length; index++) {
|
|
355
|
+
rand = _.random(0, index);
|
|
356
|
+
if (rand !== index) shuffled[index] = shuffled[rand];
|
|
357
|
+
shuffled[rand] = set[index];
|
|
358
|
+
}
|
|
297
359
|
return shuffled;
|
|
298
360
|
};
|
|
299
361
|
|
|
300
|
-
// Sample **n** random values from
|
|
301
|
-
// If **n** is not specified, returns a single random element
|
|
362
|
+
// Sample **n** random values from a collection.
|
|
363
|
+
// If **n** is not specified, returns a single random element.
|
|
302
364
|
// The internal `guard` argument allows it to work with `map`.
|
|
303
365
|
_.sample = function(obj, n, guard) {
|
|
304
|
-
if (
|
|
366
|
+
if (n == null || guard) {
|
|
367
|
+
if (!isArrayLike(obj)) obj = _.values(obj);
|
|
305
368
|
return obj[_.random(obj.length - 1)];
|
|
306
369
|
}
|
|
307
370
|
return _.shuffle(obj).slice(0, Math.max(0, n));
|
|
308
371
|
};
|
|
309
372
|
|
|
310
|
-
//
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
};
|
|
314
|
-
|
|
315
|
-
// Sort the object's values by a criterion produced by an iterator.
|
|
316
|
-
_.sortBy = function(obj, value, context) {
|
|
317
|
-
var iterator = lookupIterator(value);
|
|
373
|
+
// Sort the object's values by a criterion produced by an iteratee.
|
|
374
|
+
_.sortBy = function(obj, iteratee, context) {
|
|
375
|
+
iteratee = cb(iteratee, context);
|
|
318
376
|
return _.pluck(_.map(obj, function(value, index, list) {
|
|
319
377
|
return {
|
|
320
378
|
value: value,
|
|
321
379
|
index: index,
|
|
322
|
-
criteria:
|
|
380
|
+
criteria: iteratee(value, index, list)
|
|
323
381
|
};
|
|
324
382
|
}).sort(function(left, right) {
|
|
325
383
|
var a = left.criteria;
|
|
@@ -334,12 +392,12 @@
|
|
|
334
392
|
|
|
335
393
|
// An internal function used for aggregate "group by" operations.
|
|
336
394
|
var group = function(behavior) {
|
|
337
|
-
return function(obj,
|
|
395
|
+
return function(obj, iteratee, context) {
|
|
338
396
|
var result = {};
|
|
339
|
-
|
|
340
|
-
each(obj, function(value, index) {
|
|
341
|
-
var key =
|
|
342
|
-
behavior(result,
|
|
397
|
+
iteratee = cb(iteratee, context);
|
|
398
|
+
_.each(obj, function(value, index) {
|
|
399
|
+
var key = iteratee(value, index, obj);
|
|
400
|
+
behavior(result, value, key);
|
|
343
401
|
});
|
|
344
402
|
return result;
|
|
345
403
|
};
|
|
@@ -347,48 +405,46 @@
|
|
|
347
405
|
|
|
348
406
|
// Groups the object's values by a criterion. Pass either a string attribute
|
|
349
407
|
// to group by, or a function that returns the criterion.
|
|
350
|
-
_.groupBy = group(function(result,
|
|
351
|
-
(_.has(result, key)
|
|
408
|
+
_.groupBy = group(function(result, value, key) {
|
|
409
|
+
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
|
|
352
410
|
});
|
|
353
411
|
|
|
354
412
|
// Indexes the object's values by a criterion, similar to `groupBy`, but for
|
|
355
413
|
// when you know that your index values will be unique.
|
|
356
|
-
_.indexBy = group(function(result,
|
|
414
|
+
_.indexBy = group(function(result, value, key) {
|
|
357
415
|
result[key] = value;
|
|
358
416
|
});
|
|
359
417
|
|
|
360
418
|
// Counts instances of an object that group by a certain criterion. Pass
|
|
361
419
|
// either a string attribute to count by, or a function that returns the
|
|
362
420
|
// criterion.
|
|
363
|
-
_.countBy = group(function(result, key) {
|
|
364
|
-
_.has(result, key)
|
|
421
|
+
_.countBy = group(function(result, value, key) {
|
|
422
|
+
if (_.has(result, key)) result[key]++; else result[key] = 1;
|
|
365
423
|
});
|
|
366
424
|
|
|
367
|
-
// Use a comparator function to figure out the smallest index at which
|
|
368
|
-
// an object should be inserted so as to maintain order. Uses binary search.
|
|
369
|
-
_.sortedIndex = function(array, obj, iterator, context) {
|
|
370
|
-
iterator = iterator == null ? _.identity : lookupIterator(iterator);
|
|
371
|
-
var value = iterator.call(context, obj);
|
|
372
|
-
var low = 0, high = array.length;
|
|
373
|
-
while (low < high) {
|
|
374
|
-
var mid = (low + high) >>> 1;
|
|
375
|
-
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
|
|
376
|
-
}
|
|
377
|
-
return low;
|
|
378
|
-
};
|
|
379
|
-
|
|
380
425
|
// Safely create a real, live array from anything iterable.
|
|
381
426
|
_.toArray = function(obj) {
|
|
382
427
|
if (!obj) return [];
|
|
383
428
|
if (_.isArray(obj)) return slice.call(obj);
|
|
384
|
-
if (obj
|
|
429
|
+
if (isArrayLike(obj)) return _.map(obj, _.identity);
|
|
385
430
|
return _.values(obj);
|
|
386
431
|
};
|
|
387
432
|
|
|
388
433
|
// Return the number of elements in an object.
|
|
389
434
|
_.size = function(obj) {
|
|
390
435
|
if (obj == null) return 0;
|
|
391
|
-
return (obj
|
|
436
|
+
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
// Split a collection into two arrays: one whose elements all satisfy the given
|
|
440
|
+
// predicate, and one whose elements all do not satisfy the predicate.
|
|
441
|
+
_.partition = function(obj, predicate, context) {
|
|
442
|
+
predicate = cb(predicate, context);
|
|
443
|
+
var pass = [], fail = [];
|
|
444
|
+
_.each(obj, function(value, key, obj) {
|
|
445
|
+
(predicate(value, key, obj) ? pass : fail).push(value);
|
|
446
|
+
});
|
|
447
|
+
return [pass, fail];
|
|
392
448
|
};
|
|
393
449
|
|
|
394
450
|
// Array Functions
|
|
@@ -399,34 +455,30 @@
|
|
|
399
455
|
// allows it to work with `_.map`.
|
|
400
456
|
_.first = _.head = _.take = function(array, n, guard) {
|
|
401
457
|
if (array == null) return void 0;
|
|
402
|
-
|
|
458
|
+
if (n == null || guard) return array[0];
|
|
459
|
+
return _.initial(array, array.length - n);
|
|
403
460
|
};
|
|
404
461
|
|
|
405
462
|
// Returns everything but the last entry of the array. Especially useful on
|
|
406
463
|
// the arguments object. Passing **n** will return all the values in
|
|
407
|
-
// the array, excluding the last N.
|
|
408
|
-
// `_.map`.
|
|
464
|
+
// the array, excluding the last N.
|
|
409
465
|
_.initial = function(array, n, guard) {
|
|
410
|
-
return slice.call(array, 0, array.length - (
|
|
466
|
+
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
|
|
411
467
|
};
|
|
412
468
|
|
|
413
469
|
// Get the last element of an array. Passing **n** will return the last N
|
|
414
|
-
// values in the array.
|
|
470
|
+
// values in the array.
|
|
415
471
|
_.last = function(array, n, guard) {
|
|
416
472
|
if (array == null) return void 0;
|
|
417
|
-
if (
|
|
418
|
-
|
|
419
|
-
} else {
|
|
420
|
-
return slice.call(array, Math.max(array.length - n, 0));
|
|
421
|
-
}
|
|
473
|
+
if (n == null || guard) return array[array.length - 1];
|
|
474
|
+
return _.rest(array, Math.max(0, array.length - n));
|
|
422
475
|
};
|
|
423
476
|
|
|
424
477
|
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
|
|
425
478
|
// Especially useful on the arguments object. Passing an **n** will return
|
|
426
|
-
// the rest N values in the array.
|
|
427
|
-
// check allows it to work with `_.map`.
|
|
479
|
+
// the rest N values in the array.
|
|
428
480
|
_.rest = _.tail = _.drop = function(array, n, guard) {
|
|
429
|
-
return slice.call(array,
|
|
481
|
+
return slice.call(array, n == null || guard ? 1 : n);
|
|
430
482
|
};
|
|
431
483
|
|
|
432
484
|
// Trim out all falsy values from an array.
|
|
@@ -435,23 +487,28 @@
|
|
|
435
487
|
};
|
|
436
488
|
|
|
437
489
|
// Internal implementation of a recursive `flatten` function.
|
|
438
|
-
var flatten = function(input, shallow,
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
output.
|
|
490
|
+
var flatten = function(input, shallow, strict, startIndex) {
|
|
491
|
+
var output = [], idx = 0;
|
|
492
|
+
for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
|
|
493
|
+
var value = input[i];
|
|
494
|
+
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
|
|
495
|
+
//flatten current level of array or arguments object
|
|
496
|
+
if (!shallow) value = flatten(value, shallow, strict);
|
|
497
|
+
var j = 0, len = value.length;
|
|
498
|
+
output.length += len;
|
|
499
|
+
while (j < len) {
|
|
500
|
+
output[idx++] = value[j++];
|
|
501
|
+
}
|
|
502
|
+
} else if (!strict) {
|
|
503
|
+
output[idx++] = value;
|
|
447
504
|
}
|
|
448
|
-
}
|
|
505
|
+
}
|
|
449
506
|
return output;
|
|
450
507
|
};
|
|
451
508
|
|
|
452
509
|
// Flatten out an array, either recursively (by default), or just one level.
|
|
453
510
|
_.flatten = function(array, shallow) {
|
|
454
|
-
return flatten(array, shallow,
|
|
511
|
+
return flatten(array, shallow, false);
|
|
455
512
|
};
|
|
456
513
|
|
|
457
514
|
// Return a version of the array that does not contain the specified value(s).
|
|
@@ -462,66 +519,88 @@
|
|
|
462
519
|
// Produce a duplicate-free version of the array. If the array has already
|
|
463
520
|
// been sorted, you have the option of using a faster algorithm.
|
|
464
521
|
// Aliased as `unique`.
|
|
465
|
-
_.uniq = _.unique = function(array, isSorted,
|
|
466
|
-
if (_.
|
|
467
|
-
context =
|
|
468
|
-
|
|
522
|
+
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
|
|
523
|
+
if (!_.isBoolean(isSorted)) {
|
|
524
|
+
context = iteratee;
|
|
525
|
+
iteratee = isSorted;
|
|
469
526
|
isSorted = false;
|
|
470
527
|
}
|
|
471
|
-
|
|
472
|
-
var
|
|
528
|
+
if (iteratee != null) iteratee = cb(iteratee, context);
|
|
529
|
+
var result = [];
|
|
473
530
|
var seen = [];
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
531
|
+
for (var i = 0, length = getLength(array); i < length; i++) {
|
|
532
|
+
var value = array[i],
|
|
533
|
+
computed = iteratee ? iteratee(value, i, array) : value;
|
|
534
|
+
if (isSorted) {
|
|
535
|
+
if (!i || seen !== computed) result.push(value);
|
|
536
|
+
seen = computed;
|
|
537
|
+
} else if (iteratee) {
|
|
538
|
+
if (!_.contains(seen, computed)) {
|
|
539
|
+
seen.push(computed);
|
|
540
|
+
result.push(value);
|
|
541
|
+
}
|
|
542
|
+
} else if (!_.contains(result, value)) {
|
|
543
|
+
result.push(value);
|
|
478
544
|
}
|
|
479
|
-
}
|
|
480
|
-
return
|
|
545
|
+
}
|
|
546
|
+
return result;
|
|
481
547
|
};
|
|
482
548
|
|
|
483
549
|
// Produce an array that contains the union: each distinct element from all of
|
|
484
550
|
// the passed-in arrays.
|
|
485
551
|
_.union = function() {
|
|
486
|
-
return _.uniq(
|
|
552
|
+
return _.uniq(flatten(arguments, true, true));
|
|
487
553
|
};
|
|
488
554
|
|
|
489
555
|
// Produce an array that contains every item shared between all the
|
|
490
556
|
// passed-in arrays.
|
|
491
557
|
_.intersection = function(array) {
|
|
492
|
-
var
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
558
|
+
var result = [];
|
|
559
|
+
var argsLength = arguments.length;
|
|
560
|
+
for (var i = 0, length = getLength(array); i < length; i++) {
|
|
561
|
+
var item = array[i];
|
|
562
|
+
if (_.contains(result, item)) continue;
|
|
563
|
+
for (var j = 1; j < argsLength; j++) {
|
|
564
|
+
if (!_.contains(arguments[j], item)) break;
|
|
565
|
+
}
|
|
566
|
+
if (j === argsLength) result.push(item);
|
|
567
|
+
}
|
|
568
|
+
return result;
|
|
498
569
|
};
|
|
499
570
|
|
|
500
571
|
// Take the difference between one array and a number of other arrays.
|
|
501
572
|
// Only the elements present in just the first array will remain.
|
|
502
573
|
_.difference = function(array) {
|
|
503
|
-
var rest =
|
|
504
|
-
return _.filter(array, function(value){
|
|
574
|
+
var rest = flatten(arguments, true, true, 1);
|
|
575
|
+
return _.filter(array, function(value){
|
|
576
|
+
return !_.contains(rest, value);
|
|
577
|
+
});
|
|
505
578
|
};
|
|
506
579
|
|
|
507
580
|
// Zip together multiple lists into a single array -- elements that share
|
|
508
581
|
// an index go together.
|
|
509
582
|
_.zip = function() {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
583
|
+
return _.unzip(arguments);
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
// Complement of _.zip. Unzip accepts an array of arrays and groups
|
|
587
|
+
// each array's elements on shared indices
|
|
588
|
+
_.unzip = function(array) {
|
|
589
|
+
var length = array && _.max(array, getLength).length || 0;
|
|
590
|
+
var result = Array(length);
|
|
591
|
+
|
|
592
|
+
for (var index = 0; index < length; index++) {
|
|
593
|
+
result[index] = _.pluck(array, index);
|
|
514
594
|
}
|
|
515
|
-
return
|
|
595
|
+
return result;
|
|
516
596
|
};
|
|
517
597
|
|
|
518
598
|
// Converts lists into objects. Pass either a single array of `[key, value]`
|
|
519
599
|
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
|
520
600
|
// the corresponding values.
|
|
521
601
|
_.object = function(list, values) {
|
|
522
|
-
if (list == null) return {};
|
|
523
602
|
var result = {};
|
|
524
|
-
for (var i = 0, length = list
|
|
603
|
+
for (var i = 0, length = getLength(list); i < length; i++) {
|
|
525
604
|
if (values) {
|
|
526
605
|
result[list[i]] = values[i];
|
|
527
606
|
} else {
|
|
@@ -531,57 +610,83 @@
|
|
|
531
610
|
return result;
|
|
532
611
|
};
|
|
533
612
|
|
|
534
|
-
//
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
var i = 0, length = array.length;
|
|
543
|
-
if (isSorted) {
|
|
544
|
-
if (typeof isSorted == 'number') {
|
|
545
|
-
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
|
|
546
|
-
} else {
|
|
547
|
-
i = _.sortedIndex(array, item);
|
|
548
|
-
return array[i] === item ? i : -1;
|
|
613
|
+
// Generator function to create the findIndex and findLastIndex functions
|
|
614
|
+
function createPredicateIndexFinder(dir) {
|
|
615
|
+
return function(array, predicate, context) {
|
|
616
|
+
predicate = cb(predicate, context);
|
|
617
|
+
var length = getLength(array);
|
|
618
|
+
var index = dir > 0 ? 0 : length - 1;
|
|
619
|
+
for (; index >= 0 && index < length; index += dir) {
|
|
620
|
+
if (predicate(array[index], index, array)) return index;
|
|
549
621
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
return -1;
|
|
554
|
-
};
|
|
622
|
+
return -1;
|
|
623
|
+
};
|
|
624
|
+
}
|
|
555
625
|
|
|
556
|
-
//
|
|
557
|
-
_.
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
626
|
+
// Returns the first index on an array-like that passes a predicate test
|
|
627
|
+
_.findIndex = createPredicateIndexFinder(1);
|
|
628
|
+
_.findLastIndex = createPredicateIndexFinder(-1);
|
|
629
|
+
|
|
630
|
+
// Use a comparator function to figure out the smallest index at which
|
|
631
|
+
// an object should be inserted so as to maintain order. Uses binary search.
|
|
632
|
+
_.sortedIndex = function(array, obj, iteratee, context) {
|
|
633
|
+
iteratee = cb(iteratee, context, 1);
|
|
634
|
+
var value = iteratee(obj);
|
|
635
|
+
var low = 0, high = getLength(array);
|
|
636
|
+
while (low < high) {
|
|
637
|
+
var mid = Math.floor((low + high) / 2);
|
|
638
|
+
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
|
|
562
639
|
}
|
|
563
|
-
|
|
564
|
-
while (i--) if (array[i] === item) return i;
|
|
565
|
-
return -1;
|
|
640
|
+
return low;
|
|
566
641
|
};
|
|
567
642
|
|
|
643
|
+
// Generator function to create the indexOf and lastIndexOf functions
|
|
644
|
+
function createIndexFinder(dir, predicateFind, sortedIndex) {
|
|
645
|
+
return function(array, item, idx) {
|
|
646
|
+
var i = 0, length = getLength(array);
|
|
647
|
+
if (typeof idx == 'number') {
|
|
648
|
+
if (dir > 0) {
|
|
649
|
+
i = idx >= 0 ? idx : Math.max(idx + length, i);
|
|
650
|
+
} else {
|
|
651
|
+
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
|
|
652
|
+
}
|
|
653
|
+
} else if (sortedIndex && idx && length) {
|
|
654
|
+
idx = sortedIndex(array, item);
|
|
655
|
+
return array[idx] === item ? idx : -1;
|
|
656
|
+
}
|
|
657
|
+
if (item !== item) {
|
|
658
|
+
idx = predicateFind(slice.call(array, i, length), _.isNaN);
|
|
659
|
+
return idx >= 0 ? idx + i : -1;
|
|
660
|
+
}
|
|
661
|
+
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
|
|
662
|
+
if (array[idx] === item) return idx;
|
|
663
|
+
}
|
|
664
|
+
return -1;
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// Return the position of the first occurrence of an item in an array,
|
|
669
|
+
// or -1 if the item is not included in the array.
|
|
670
|
+
// If the array is large and already in sort order, pass `true`
|
|
671
|
+
// for **isSorted** to use binary search.
|
|
672
|
+
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
|
|
673
|
+
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
|
|
674
|
+
|
|
568
675
|
// Generate an integer Array containing an arithmetic progression. A port of
|
|
569
676
|
// the native Python `range()` function. See
|
|
570
677
|
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
|
571
678
|
_.range = function(start, stop, step) {
|
|
572
|
-
if (
|
|
679
|
+
if (stop == null) {
|
|
573
680
|
stop = start || 0;
|
|
574
681
|
start = 0;
|
|
575
682
|
}
|
|
576
|
-
step =
|
|
683
|
+
step = step || 1;
|
|
577
684
|
|
|
578
685
|
var length = Math.max(Math.ceil((stop - start) / step), 0);
|
|
579
|
-
var
|
|
580
|
-
var range = new Array(length);
|
|
686
|
+
var range = Array(length);
|
|
581
687
|
|
|
582
|
-
|
|
583
|
-
range[idx
|
|
584
|
-
start += step;
|
|
688
|
+
for (var idx = 0; idx < length; idx++, start += step) {
|
|
689
|
+
range[idx] = start;
|
|
585
690
|
}
|
|
586
691
|
|
|
587
692
|
return range;
|
|
@@ -590,68 +695,83 @@
|
|
|
590
695
|
// Function (ahem) Functions
|
|
591
696
|
// ------------------
|
|
592
697
|
|
|
593
|
-
//
|
|
594
|
-
|
|
698
|
+
// Determines whether to execute a function as a constructor
|
|
699
|
+
// or a normal function with the provided arguments
|
|
700
|
+
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
|
|
701
|
+
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
|
|
702
|
+
var self = baseCreate(sourceFunc.prototype);
|
|
703
|
+
var result = sourceFunc.apply(self, args);
|
|
704
|
+
if (_.isObject(result)) return result;
|
|
705
|
+
return self;
|
|
706
|
+
};
|
|
595
707
|
|
|
596
708
|
// Create a function bound to a given object (assigning `this`, and arguments,
|
|
597
709
|
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
|
|
598
710
|
// available.
|
|
599
711
|
_.bind = function(func, context) {
|
|
600
|
-
var args, bound;
|
|
601
712
|
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
|
602
|
-
if (!_.isFunction(func)) throw new TypeError;
|
|
603
|
-
args = slice.call(arguments, 2);
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
ctor.prototype = func.prototype;
|
|
607
|
-
var self = new ctor;
|
|
608
|
-
ctor.prototype = null;
|
|
609
|
-
var result = func.apply(self, args.concat(slice.call(arguments)));
|
|
610
|
-
if (Object(result) === result) return result;
|
|
611
|
-
return self;
|
|
713
|
+
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
|
|
714
|
+
var args = slice.call(arguments, 2);
|
|
715
|
+
var bound = function() {
|
|
716
|
+
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
|
|
612
717
|
};
|
|
718
|
+
return bound;
|
|
613
719
|
};
|
|
614
720
|
|
|
615
721
|
// Partially apply a function by creating a version that has had some of its
|
|
616
|
-
// arguments pre-filled, without changing its dynamic `this` context.
|
|
722
|
+
// arguments pre-filled, without changing its dynamic `this` context. _ acts
|
|
723
|
+
// as a placeholder, allowing any combination of arguments to be pre-filled.
|
|
617
724
|
_.partial = function(func) {
|
|
618
|
-
var
|
|
619
|
-
|
|
620
|
-
|
|
725
|
+
var boundArgs = slice.call(arguments, 1);
|
|
726
|
+
var bound = function() {
|
|
727
|
+
var position = 0, length = boundArgs.length;
|
|
728
|
+
var args = Array(length);
|
|
729
|
+
for (var i = 0; i < length; i++) {
|
|
730
|
+
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
|
|
731
|
+
}
|
|
732
|
+
while (position < arguments.length) args.push(arguments[position++]);
|
|
733
|
+
return executeBound(func, bound, this, this, args);
|
|
621
734
|
};
|
|
735
|
+
return bound;
|
|
622
736
|
};
|
|
623
737
|
|
|
624
|
-
// Bind
|
|
625
|
-
//
|
|
738
|
+
// Bind a number of an object's methods to that object. Remaining arguments
|
|
739
|
+
// are the method names to be bound. Useful for ensuring that all callbacks
|
|
740
|
+
// defined on an object belong to it.
|
|
626
741
|
_.bindAll = function(obj) {
|
|
627
|
-
var
|
|
628
|
-
if (
|
|
629
|
-
|
|
742
|
+
var i, length = arguments.length, key;
|
|
743
|
+
if (length <= 1) throw new Error('bindAll must be passed function names');
|
|
744
|
+
for (i = 1; i < length; i++) {
|
|
745
|
+
key = arguments[i];
|
|
746
|
+
obj[key] = _.bind(obj[key], obj);
|
|
747
|
+
}
|
|
630
748
|
return obj;
|
|
631
749
|
};
|
|
632
750
|
|
|
633
751
|
// Memoize an expensive function by storing its results.
|
|
634
752
|
_.memoize = function(func, hasher) {
|
|
635
|
-
var
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
return
|
|
753
|
+
var memoize = function(key) {
|
|
754
|
+
var cache = memoize.cache;
|
|
755
|
+
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
|
|
756
|
+
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
|
|
757
|
+
return cache[address];
|
|
640
758
|
};
|
|
759
|
+
memoize.cache = {};
|
|
760
|
+
return memoize;
|
|
641
761
|
};
|
|
642
762
|
|
|
643
763
|
// Delays a function for the given number of milliseconds, and then calls
|
|
644
764
|
// it with the arguments supplied.
|
|
645
765
|
_.delay = function(func, wait) {
|
|
646
766
|
var args = slice.call(arguments, 2);
|
|
647
|
-
return setTimeout(function(){
|
|
767
|
+
return setTimeout(function(){
|
|
768
|
+
return func.apply(null, args);
|
|
769
|
+
}, wait);
|
|
648
770
|
};
|
|
649
771
|
|
|
650
772
|
// Defers a function, scheduling it to run after the current call stack has
|
|
651
773
|
// cleared.
|
|
652
|
-
_.defer =
|
|
653
|
-
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
|
|
654
|
-
};
|
|
774
|
+
_.defer = _.partial(_.delay, _, 1);
|
|
655
775
|
|
|
656
776
|
// Returns a function, that, when invoked, will only be triggered at most once
|
|
657
777
|
// during a given window of time. Normally, the throttled function will run
|
|
@@ -662,23 +782,27 @@
|
|
|
662
782
|
var context, args, result;
|
|
663
783
|
var timeout = null;
|
|
664
784
|
var previous = 0;
|
|
665
|
-
|
|
785
|
+
if (!options) options = {};
|
|
666
786
|
var later = function() {
|
|
667
|
-
previous = options.leading === false ? 0 :
|
|
787
|
+
previous = options.leading === false ? 0 : _.now();
|
|
668
788
|
timeout = null;
|
|
669
789
|
result = func.apply(context, args);
|
|
790
|
+
if (!timeout) context = args = null;
|
|
670
791
|
};
|
|
671
792
|
return function() {
|
|
672
|
-
var now =
|
|
793
|
+
var now = _.now();
|
|
673
794
|
if (!previous && options.leading === false) previous = now;
|
|
674
795
|
var remaining = wait - (now - previous);
|
|
675
796
|
context = this;
|
|
676
797
|
args = arguments;
|
|
677
|
-
if (remaining <= 0) {
|
|
678
|
-
|
|
679
|
-
|
|
798
|
+
if (remaining <= 0 || remaining > wait) {
|
|
799
|
+
if (timeout) {
|
|
800
|
+
clearTimeout(timeout);
|
|
801
|
+
timeout = null;
|
|
802
|
+
}
|
|
680
803
|
previous = now;
|
|
681
804
|
result = func.apply(context, args);
|
|
805
|
+
if (!timeout) context = args = null;
|
|
682
806
|
} else if (!timeout && options.trailing !== false) {
|
|
683
807
|
timeout = setTimeout(later, remaining);
|
|
684
808
|
}
|
|
@@ -692,38 +816,33 @@
|
|
|
692
816
|
// leading edge, instead of the trailing.
|
|
693
817
|
_.debounce = function(func, wait, immediate) {
|
|
694
818
|
var timeout, args, context, timestamp, result;
|
|
819
|
+
|
|
820
|
+
var later = function() {
|
|
821
|
+
var last = _.now() - timestamp;
|
|
822
|
+
|
|
823
|
+
if (last < wait && last >= 0) {
|
|
824
|
+
timeout = setTimeout(later, wait - last);
|
|
825
|
+
} else {
|
|
826
|
+
timeout = null;
|
|
827
|
+
if (!immediate) {
|
|
828
|
+
result = func.apply(context, args);
|
|
829
|
+
if (!timeout) context = args = null;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
|
|
695
834
|
return function() {
|
|
696
835
|
context = this;
|
|
697
836
|
args = arguments;
|
|
698
|
-
timestamp =
|
|
699
|
-
var later = function() {
|
|
700
|
-
var last = (new Date()) - timestamp;
|
|
701
|
-
if (last < wait) {
|
|
702
|
-
timeout = setTimeout(later, wait - last);
|
|
703
|
-
} else {
|
|
704
|
-
timeout = null;
|
|
705
|
-
if (!immediate) result = func.apply(context, args);
|
|
706
|
-
}
|
|
707
|
-
};
|
|
837
|
+
timestamp = _.now();
|
|
708
838
|
var callNow = immediate && !timeout;
|
|
709
|
-
if (!timeout)
|
|
710
|
-
|
|
839
|
+
if (!timeout) timeout = setTimeout(later, wait);
|
|
840
|
+
if (callNow) {
|
|
841
|
+
result = func.apply(context, args);
|
|
842
|
+
context = args = null;
|
|
711
843
|
}
|
|
712
|
-
if (callNow) result = func.apply(context, args);
|
|
713
|
-
return result;
|
|
714
|
-
};
|
|
715
|
-
};
|
|
716
844
|
|
|
717
|
-
|
|
718
|
-
// often you call it. Useful for lazy initialization.
|
|
719
|
-
_.once = function(func) {
|
|
720
|
-
var ran = false, memo;
|
|
721
|
-
return function() {
|
|
722
|
-
if (ran) return memo;
|
|
723
|
-
ran = true;
|
|
724
|
-
memo = func.apply(this, arguments);
|
|
725
|
-
func = null;
|
|
726
|
-
return memo;
|
|
845
|
+
return result;
|
|
727
846
|
};
|
|
728
847
|
};
|
|
729
848
|
|
|
@@ -731,27 +850,30 @@
|
|
|
731
850
|
// allowing you to adjust arguments, run code before and after, and
|
|
732
851
|
// conditionally execute the original function.
|
|
733
852
|
_.wrap = function(func, wrapper) {
|
|
853
|
+
return _.partial(wrapper, func);
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
// Returns a negated version of the passed-in predicate.
|
|
857
|
+
_.negate = function(predicate) {
|
|
734
858
|
return function() {
|
|
735
|
-
|
|
736
|
-
push.apply(args, arguments);
|
|
737
|
-
return wrapper.apply(this, args);
|
|
859
|
+
return !predicate.apply(this, arguments);
|
|
738
860
|
};
|
|
739
861
|
};
|
|
740
862
|
|
|
741
863
|
// Returns a function that is the composition of a list of functions, each
|
|
742
864
|
// consuming the return value of the function that follows.
|
|
743
865
|
_.compose = function() {
|
|
744
|
-
var
|
|
866
|
+
var args = arguments;
|
|
867
|
+
var start = args.length - 1;
|
|
745
868
|
return function() {
|
|
746
|
-
var
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
return args[0];
|
|
869
|
+
var i = start;
|
|
870
|
+
var result = args[start].apply(this, arguments);
|
|
871
|
+
while (i--) result = args[i].call(this, result);
|
|
872
|
+
return result;
|
|
751
873
|
};
|
|
752
874
|
};
|
|
753
875
|
|
|
754
|
-
// Returns a function that will only be executed after
|
|
876
|
+
// Returns a function that will only be executed on and after the Nth call.
|
|
755
877
|
_.after = function(times, func) {
|
|
756
878
|
return function() {
|
|
757
879
|
if (--times < 1) {
|
|
@@ -760,15 +882,66 @@
|
|
|
760
882
|
};
|
|
761
883
|
};
|
|
762
884
|
|
|
885
|
+
// Returns a function that will only be executed up to (but not including) the Nth call.
|
|
886
|
+
_.before = function(times, func) {
|
|
887
|
+
var memo;
|
|
888
|
+
return function() {
|
|
889
|
+
if (--times > 0) {
|
|
890
|
+
memo = func.apply(this, arguments);
|
|
891
|
+
}
|
|
892
|
+
if (times <= 1) func = null;
|
|
893
|
+
return memo;
|
|
894
|
+
};
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
// Returns a function that will be executed at most one time, no matter how
|
|
898
|
+
// often you call it. Useful for lazy initialization.
|
|
899
|
+
_.once = _.partial(_.before, 2);
|
|
900
|
+
|
|
763
901
|
// Object Functions
|
|
764
902
|
// ----------------
|
|
765
903
|
|
|
766
|
-
//
|
|
904
|
+
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
|
|
905
|
+
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
|
|
906
|
+
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
|
|
907
|
+
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
|
|
908
|
+
|
|
909
|
+
function collectNonEnumProps(obj, keys) {
|
|
910
|
+
var nonEnumIdx = nonEnumerableProps.length;
|
|
911
|
+
var constructor = obj.constructor;
|
|
912
|
+
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
|
|
913
|
+
|
|
914
|
+
// Constructor is a special case.
|
|
915
|
+
var prop = 'constructor';
|
|
916
|
+
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
|
|
917
|
+
|
|
918
|
+
while (nonEnumIdx--) {
|
|
919
|
+
prop = nonEnumerableProps[nonEnumIdx];
|
|
920
|
+
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
|
|
921
|
+
keys.push(prop);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// Retrieve the names of an object's own properties.
|
|
767
927
|
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
|
768
|
-
_.keys =
|
|
769
|
-
if (
|
|
928
|
+
_.keys = function(obj) {
|
|
929
|
+
if (!_.isObject(obj)) return [];
|
|
930
|
+
if (nativeKeys) return nativeKeys(obj);
|
|
770
931
|
var keys = [];
|
|
771
932
|
for (var key in obj) if (_.has(obj, key)) keys.push(key);
|
|
933
|
+
// Ahem, IE < 9.
|
|
934
|
+
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
|
935
|
+
return keys;
|
|
936
|
+
};
|
|
937
|
+
|
|
938
|
+
// Retrieve all the property names of an object.
|
|
939
|
+
_.allKeys = function(obj) {
|
|
940
|
+
if (!_.isObject(obj)) return [];
|
|
941
|
+
var keys = [];
|
|
942
|
+
for (var key in obj) keys.push(key);
|
|
943
|
+
// Ahem, IE < 9.
|
|
944
|
+
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
|
772
945
|
return keys;
|
|
773
946
|
};
|
|
774
947
|
|
|
@@ -776,18 +949,33 @@
|
|
|
776
949
|
_.values = function(obj) {
|
|
777
950
|
var keys = _.keys(obj);
|
|
778
951
|
var length = keys.length;
|
|
779
|
-
var values =
|
|
952
|
+
var values = Array(length);
|
|
780
953
|
for (var i = 0; i < length; i++) {
|
|
781
954
|
values[i] = obj[keys[i]];
|
|
782
955
|
}
|
|
783
956
|
return values;
|
|
784
957
|
};
|
|
785
958
|
|
|
959
|
+
// Returns the results of applying the iteratee to each element of the object
|
|
960
|
+
// In contrast to _.map it returns an object
|
|
961
|
+
_.mapObject = function(obj, iteratee, context) {
|
|
962
|
+
iteratee = cb(iteratee, context);
|
|
963
|
+
var keys = _.keys(obj),
|
|
964
|
+
length = keys.length,
|
|
965
|
+
results = {},
|
|
966
|
+
currentKey;
|
|
967
|
+
for (var index = 0; index < length; index++) {
|
|
968
|
+
currentKey = keys[index];
|
|
969
|
+
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
|
|
970
|
+
}
|
|
971
|
+
return results;
|
|
972
|
+
};
|
|
973
|
+
|
|
786
974
|
// Convert an object into a list of `[key, value]` pairs.
|
|
787
975
|
_.pairs = function(obj) {
|
|
788
976
|
var keys = _.keys(obj);
|
|
789
977
|
var length = keys.length;
|
|
790
|
-
var pairs =
|
|
978
|
+
var pairs = Array(length);
|
|
791
979
|
for (var i = 0; i < length; i++) {
|
|
792
980
|
pairs[i] = [keys[i], obj[keys[i]]];
|
|
793
981
|
}
|
|
@@ -815,47 +1003,65 @@
|
|
|
815
1003
|
};
|
|
816
1004
|
|
|
817
1005
|
// Extend a given object with all the properties in passed-in object(s).
|
|
818
|
-
_.extend =
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
1006
|
+
_.extend = createAssigner(_.allKeys);
|
|
1007
|
+
|
|
1008
|
+
// Assigns a given object with all the own properties in the passed-in object(s)
|
|
1009
|
+
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
|
|
1010
|
+
_.extendOwn = _.assign = createAssigner(_.keys);
|
|
1011
|
+
|
|
1012
|
+
// Returns the first key on an object that passes a predicate test
|
|
1013
|
+
_.findKey = function(obj, predicate, context) {
|
|
1014
|
+
predicate = cb(predicate, context);
|
|
1015
|
+
var keys = _.keys(obj), key;
|
|
1016
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
|
1017
|
+
key = keys[i];
|
|
1018
|
+
if (predicate(obj[key], key, obj)) return key;
|
|
1019
|
+
}
|
|
827
1020
|
};
|
|
828
1021
|
|
|
829
1022
|
// Return a copy of the object only containing the whitelisted properties.
|
|
830
|
-
_.pick = function(
|
|
831
|
-
var
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1023
|
+
_.pick = function(object, oiteratee, context) {
|
|
1024
|
+
var result = {}, obj = object, iteratee, keys;
|
|
1025
|
+
if (obj == null) return result;
|
|
1026
|
+
if (_.isFunction(oiteratee)) {
|
|
1027
|
+
keys = _.allKeys(obj);
|
|
1028
|
+
iteratee = optimizeCb(oiteratee, context);
|
|
1029
|
+
} else {
|
|
1030
|
+
keys = flatten(arguments, false, false, 1);
|
|
1031
|
+
iteratee = function(value, key, obj) { return key in obj; };
|
|
1032
|
+
obj = Object(obj);
|
|
1033
|
+
}
|
|
1034
|
+
for (var i = 0, length = keys.length; i < length; i++) {
|
|
1035
|
+
var key = keys[i];
|
|
1036
|
+
var value = obj[key];
|
|
1037
|
+
if (iteratee(value, key, obj)) result[key] = value;
|
|
1038
|
+
}
|
|
1039
|
+
return result;
|
|
837
1040
|
};
|
|
838
1041
|
|
|
839
1042
|
// Return a copy of the object without the blacklisted properties.
|
|
840
|
-
_.omit = function(obj) {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1043
|
+
_.omit = function(obj, iteratee, context) {
|
|
1044
|
+
if (_.isFunction(iteratee)) {
|
|
1045
|
+
iteratee = _.negate(iteratee);
|
|
1046
|
+
} else {
|
|
1047
|
+
var keys = _.map(flatten(arguments, false, false, 1), String);
|
|
1048
|
+
iteratee = function(value, key) {
|
|
1049
|
+
return !_.contains(keys, key);
|
|
1050
|
+
};
|
|
845
1051
|
}
|
|
846
|
-
return
|
|
1052
|
+
return _.pick(obj, iteratee, context);
|
|
847
1053
|
};
|
|
848
1054
|
|
|
849
1055
|
// Fill in a given object with default properties.
|
|
850
|
-
_.defaults =
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
return
|
|
1056
|
+
_.defaults = createAssigner(_.allKeys, true);
|
|
1057
|
+
|
|
1058
|
+
// Creates an object that inherits from the given prototype object.
|
|
1059
|
+
// If additional properties are provided then they will be added to the
|
|
1060
|
+
// created object.
|
|
1061
|
+
_.create = function(prototype, props) {
|
|
1062
|
+
var result = baseCreate(prototype);
|
|
1063
|
+
if (props) _.extendOwn(result, props);
|
|
1064
|
+
return result;
|
|
859
1065
|
};
|
|
860
1066
|
|
|
861
1067
|
// Create a (shallow-cloned) duplicate of an object.
|
|
@@ -872,11 +1078,24 @@
|
|
|
872
1078
|
return obj;
|
|
873
1079
|
};
|
|
874
1080
|
|
|
1081
|
+
// Returns whether an object has a given set of `key:value` pairs.
|
|
1082
|
+
_.isMatch = function(object, attrs) {
|
|
1083
|
+
var keys = _.keys(attrs), length = keys.length;
|
|
1084
|
+
if (object == null) return !length;
|
|
1085
|
+
var obj = Object(object);
|
|
1086
|
+
for (var i = 0; i < length; i++) {
|
|
1087
|
+
var key = keys[i];
|
|
1088
|
+
if (attrs[key] !== obj[key] || !(key in obj)) return false;
|
|
1089
|
+
}
|
|
1090
|
+
return true;
|
|
1091
|
+
};
|
|
1092
|
+
|
|
1093
|
+
|
|
875
1094
|
// Internal recursive comparison function for `isEqual`.
|
|
876
1095
|
var eq = function(a, b, aStack, bStack) {
|
|
877
1096
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
|
878
1097
|
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
|
879
|
-
if (a === b) return a !== 0 || 1 / a
|
|
1098
|
+
if (a === b) return a !== 0 || 1 / a === 1 / b;
|
|
880
1099
|
// A strict comparison is necessary because `null == undefined`.
|
|
881
1100
|
if (a == null || b == null) return a === b;
|
|
882
1101
|
// Unwrap any wrapped objects.
|
|
@@ -884,97 +1103,98 @@
|
|
|
884
1103
|
if (b instanceof _) b = b._wrapped;
|
|
885
1104
|
// Compare `[[Class]]` names.
|
|
886
1105
|
var className = toString.call(a);
|
|
887
|
-
if (className
|
|
1106
|
+
if (className !== toString.call(b)) return false;
|
|
888
1107
|
switch (className) {
|
|
889
|
-
// Strings, numbers, dates, and booleans are compared by value.
|
|
1108
|
+
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
|
|
1109
|
+
case '[object RegExp]':
|
|
1110
|
+
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
|
|
890
1111
|
case '[object String]':
|
|
891
1112
|
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
|
892
1113
|
// equivalent to `new String("5")`.
|
|
893
|
-
return a
|
|
1114
|
+
return '' + a === '' + b;
|
|
894
1115
|
case '[object Number]':
|
|
895
|
-
// `NaN`s are equivalent, but non-reflexive.
|
|
896
|
-
//
|
|
897
|
-
|
|
1116
|
+
// `NaN`s are equivalent, but non-reflexive.
|
|
1117
|
+
// Object(NaN) is equivalent to NaN
|
|
1118
|
+
if (+a !== +a) return +b !== +b;
|
|
1119
|
+
// An `egal` comparison is performed for other numeric values.
|
|
1120
|
+
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
|
|
898
1121
|
case '[object Date]':
|
|
899
1122
|
case '[object Boolean]':
|
|
900
1123
|
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
|
901
1124
|
// millisecond representations. Note that invalid dates with millisecond representations
|
|
902
1125
|
// of `NaN` are not equivalent.
|
|
903
|
-
return +a
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1126
|
+
return +a === +b;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
var areArrays = className === '[object Array]';
|
|
1130
|
+
if (!areArrays) {
|
|
1131
|
+
if (typeof a != 'object' || typeof b != 'object') return false;
|
|
1132
|
+
|
|
1133
|
+
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
|
|
1134
|
+
// from different frames are.
|
|
1135
|
+
var aCtor = a.constructor, bCtor = b.constructor;
|
|
1136
|
+
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
|
|
1137
|
+
_.isFunction(bCtor) && bCtor instanceof bCtor)
|
|
1138
|
+
&& ('constructor' in a && 'constructor' in b)) {
|
|
1139
|
+
return false;
|
|
1140
|
+
}
|
|
910
1141
|
}
|
|
911
|
-
if (typeof a != 'object' || typeof b != 'object') return false;
|
|
912
1142
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
|
913
1143
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
|
1144
|
+
|
|
1145
|
+
// Initializing stack of traversed objects.
|
|
1146
|
+
// It's done here since we only need them for objects and arrays comparison.
|
|
1147
|
+
aStack = aStack || [];
|
|
1148
|
+
bStack = bStack || [];
|
|
914
1149
|
var length = aStack.length;
|
|
915
1150
|
while (length--) {
|
|
916
1151
|
// Linear search. Performance is inversely proportional to the number of
|
|
917
1152
|
// unique nested structures.
|
|
918
|
-
if (aStack[length]
|
|
919
|
-
}
|
|
920
|
-
// Objects with different constructors are not equivalent, but `Object`s
|
|
921
|
-
// from different frames are.
|
|
922
|
-
var aCtor = a.constructor, bCtor = b.constructor;
|
|
923
|
-
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
|
|
924
|
-
_.isFunction(bCtor) && (bCtor instanceof bCtor))) {
|
|
925
|
-
return false;
|
|
1153
|
+
if (aStack[length] === a) return bStack[length] === b;
|
|
926
1154
|
}
|
|
1155
|
+
|
|
927
1156
|
// Add the first object to the stack of traversed objects.
|
|
928
1157
|
aStack.push(a);
|
|
929
1158
|
bStack.push(b);
|
|
930
|
-
|
|
1159
|
+
|
|
931
1160
|
// Recursively compare objects and arrays.
|
|
932
|
-
if (
|
|
1161
|
+
if (areArrays) {
|
|
933
1162
|
// Compare array lengths to determine if a deep comparison is necessary.
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
if (!(result = eq(a[size], b[size], aStack, bStack))) break;
|
|
940
|
-
}
|
|
1163
|
+
length = a.length;
|
|
1164
|
+
if (length !== b.length) return false;
|
|
1165
|
+
// Deep compare the contents, ignoring non-numeric properties.
|
|
1166
|
+
while (length--) {
|
|
1167
|
+
if (!eq(a[length], b[length], aStack, bStack)) return false;
|
|
941
1168
|
}
|
|
942
1169
|
} else {
|
|
943
1170
|
// Deep compare objects.
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
// Ensure that both objects contain the same number of properties.
|
|
953
|
-
if (result) {
|
|
954
|
-
for (key in b) {
|
|
955
|
-
if (_.has(b, key) && !(size--)) break;
|
|
956
|
-
}
|
|
957
|
-
result = !size;
|
|
1171
|
+
var keys = _.keys(a), key;
|
|
1172
|
+
length = keys.length;
|
|
1173
|
+
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
|
1174
|
+
if (_.keys(b).length !== length) return false;
|
|
1175
|
+
while (length--) {
|
|
1176
|
+
// Deep compare each member
|
|
1177
|
+
key = keys[length];
|
|
1178
|
+
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
|
|
958
1179
|
}
|
|
959
1180
|
}
|
|
960
1181
|
// Remove the first object from the stack of traversed objects.
|
|
961
1182
|
aStack.pop();
|
|
962
1183
|
bStack.pop();
|
|
963
|
-
return
|
|
1184
|
+
return true;
|
|
964
1185
|
};
|
|
965
1186
|
|
|
966
1187
|
// Perform a deep comparison to check if two objects are equal.
|
|
967
1188
|
_.isEqual = function(a, b) {
|
|
968
|
-
return eq(a, b
|
|
1189
|
+
return eq(a, b);
|
|
969
1190
|
};
|
|
970
1191
|
|
|
971
1192
|
// Is a given array, string, or object empty?
|
|
972
1193
|
// An "empty" object has no enumerable own-properties.
|
|
973
1194
|
_.isEmpty = function(obj) {
|
|
974
1195
|
if (obj == null) return true;
|
|
975
|
-
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
|
976
|
-
|
|
977
|
-
return true;
|
|
1196
|
+
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
|
|
1197
|
+
return _.keys(obj).length === 0;
|
|
978
1198
|
};
|
|
979
1199
|
|
|
980
1200
|
// Is a given value a DOM element?
|
|
@@ -985,33 +1205,35 @@
|
|
|
985
1205
|
// Is a given value an array?
|
|
986
1206
|
// Delegates to ECMA5's native Array.isArray
|
|
987
1207
|
_.isArray = nativeIsArray || function(obj) {
|
|
988
|
-
return toString.call(obj)
|
|
1208
|
+
return toString.call(obj) === '[object Array]';
|
|
989
1209
|
};
|
|
990
1210
|
|
|
991
1211
|
// Is a given variable an object?
|
|
992
1212
|
_.isObject = function(obj) {
|
|
993
|
-
|
|
1213
|
+
var type = typeof obj;
|
|
1214
|
+
return type === 'function' || type === 'object' && !!obj;
|
|
994
1215
|
};
|
|
995
1216
|
|
|
996
|
-
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
|
|
997
|
-
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
|
|
1217
|
+
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
|
|
1218
|
+
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
|
|
998
1219
|
_['is' + name] = function(obj) {
|
|
999
|
-
return toString.call(obj)
|
|
1220
|
+
return toString.call(obj) === '[object ' + name + ']';
|
|
1000
1221
|
};
|
|
1001
1222
|
});
|
|
1002
1223
|
|
|
1003
|
-
// Define a fallback version of the method in browsers (ahem, IE), where
|
|
1224
|
+
// Define a fallback version of the method in browsers (ahem, IE < 9), where
|
|
1004
1225
|
// there isn't any inspectable "Arguments" type.
|
|
1005
1226
|
if (!_.isArguments(arguments)) {
|
|
1006
1227
|
_.isArguments = function(obj) {
|
|
1007
|
-
return
|
|
1228
|
+
return _.has(obj, 'callee');
|
|
1008
1229
|
};
|
|
1009
1230
|
}
|
|
1010
1231
|
|
|
1011
|
-
// Optimize `isFunction` if appropriate.
|
|
1012
|
-
|
|
1232
|
+
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
|
|
1233
|
+
// IE 11 (#1621), and in Safari 8 (#1929).
|
|
1234
|
+
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
|
|
1013
1235
|
_.isFunction = function(obj) {
|
|
1014
|
-
return typeof obj
|
|
1236
|
+
return typeof obj == 'function' || false;
|
|
1015
1237
|
};
|
|
1016
1238
|
}
|
|
1017
1239
|
|
|
@@ -1022,12 +1244,12 @@
|
|
|
1022
1244
|
|
|
1023
1245
|
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
|
1024
1246
|
_.isNaN = function(obj) {
|
|
1025
|
-
return _.isNumber(obj) && obj
|
|
1247
|
+
return _.isNumber(obj) && obj !== +obj;
|
|
1026
1248
|
};
|
|
1027
1249
|
|
|
1028
1250
|
// Is a given value a boolean?
|
|
1029
1251
|
_.isBoolean = function(obj) {
|
|
1030
|
-
return obj === true || obj === false || toString.call(obj)
|
|
1252
|
+
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
|
|
1031
1253
|
};
|
|
1032
1254
|
|
|
1033
1255
|
// Is a given value equal to null?
|
|
@@ -1043,7 +1265,7 @@
|
|
|
1043
1265
|
// Shortcut function for checking if an object has a given property directly
|
|
1044
1266
|
// on itself (in other words, not on a prototype).
|
|
1045
1267
|
_.has = function(obj, key) {
|
|
1046
|
-
return hasOwnProperty.call(obj, key);
|
|
1268
|
+
return obj != null && hasOwnProperty.call(obj, key);
|
|
1047
1269
|
};
|
|
1048
1270
|
|
|
1049
1271
|
// Utility Functions
|
|
@@ -1056,15 +1278,43 @@
|
|
|
1056
1278
|
return this;
|
|
1057
1279
|
};
|
|
1058
1280
|
|
|
1059
|
-
// Keep the identity function around for default
|
|
1281
|
+
// Keep the identity function around for default iteratees.
|
|
1060
1282
|
_.identity = function(value) {
|
|
1061
1283
|
return value;
|
|
1062
1284
|
};
|
|
1063
1285
|
|
|
1286
|
+
// Predicate-generating functions. Often useful outside of Underscore.
|
|
1287
|
+
_.constant = function(value) {
|
|
1288
|
+
return function() {
|
|
1289
|
+
return value;
|
|
1290
|
+
};
|
|
1291
|
+
};
|
|
1292
|
+
|
|
1293
|
+
_.noop = function(){};
|
|
1294
|
+
|
|
1295
|
+
_.property = property;
|
|
1296
|
+
|
|
1297
|
+
// Generates a function for a given object that returns a given property.
|
|
1298
|
+
_.propertyOf = function(obj) {
|
|
1299
|
+
return obj == null ? function(){} : function(key) {
|
|
1300
|
+
return obj[key];
|
|
1301
|
+
};
|
|
1302
|
+
};
|
|
1303
|
+
|
|
1304
|
+
// Returns a predicate for checking whether an object has a given set of
|
|
1305
|
+
// `key:value` pairs.
|
|
1306
|
+
_.matcher = _.matches = function(attrs) {
|
|
1307
|
+
attrs = _.extendOwn({}, attrs);
|
|
1308
|
+
return function(obj) {
|
|
1309
|
+
return _.isMatch(obj, attrs);
|
|
1310
|
+
};
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1064
1313
|
// Run a function **n** times.
|
|
1065
|
-
_.times = function(n,
|
|
1314
|
+
_.times = function(n, iteratee, context) {
|
|
1066
1315
|
var accum = Array(Math.max(0, n));
|
|
1067
|
-
|
|
1316
|
+
iteratee = optimizeCb(iteratee, context, 1);
|
|
1317
|
+
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
|
|
1068
1318
|
return accum;
|
|
1069
1319
|
};
|
|
1070
1320
|
|
|
@@ -1077,54 +1327,49 @@
|
|
|
1077
1327
|
return min + Math.floor(Math.random() * (max - min + 1));
|
|
1078
1328
|
};
|
|
1079
1329
|
|
|
1080
|
-
//
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
'&': '&',
|
|
1084
|
-
'<': '<',
|
|
1085
|
-
'>': '>',
|
|
1086
|
-
'"': '"',
|
|
1087
|
-
"'": '''
|
|
1088
|
-
}
|
|
1330
|
+
// A (possibly faster) way to get the current timestamp as an integer.
|
|
1331
|
+
_.now = Date.now || function() {
|
|
1332
|
+
return new Date().getTime();
|
|
1089
1333
|
};
|
|
1090
|
-
entityMap.unescape = _.invert(entityMap.escape);
|
|
1091
1334
|
|
|
1092
|
-
|
|
1093
|
-
var
|
|
1094
|
-
|
|
1095
|
-
|
|
1335
|
+
// List of HTML entities for escaping.
|
|
1336
|
+
var escapeMap = {
|
|
1337
|
+
'&': '&',
|
|
1338
|
+
'<': '<',
|
|
1339
|
+
'>': '>',
|
|
1340
|
+
'"': '"',
|
|
1341
|
+
"'": ''',
|
|
1342
|
+
'`': '`'
|
|
1096
1343
|
};
|
|
1344
|
+
var unescapeMap = _.invert(escapeMap);
|
|
1097
1345
|
|
|
1098
1346
|
// Functions for escaping and unescaping strings to/from HTML interpolation.
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
return ('' + string).replace(entityRegexes[method], function(match) {
|
|
1103
|
-
return entityMap[method][match];
|
|
1104
|
-
});
|
|
1347
|
+
var createEscaper = function(map) {
|
|
1348
|
+
var escaper = function(match) {
|
|
1349
|
+
return map[match];
|
|
1105
1350
|
};
|
|
1106
|
-
|
|
1351
|
+
// Regexes for identifying a key that needs to be escaped
|
|
1352
|
+
var source = '(?:' + _.keys(map).join('|') + ')';
|
|
1353
|
+
var testRegexp = RegExp(source);
|
|
1354
|
+
var replaceRegexp = RegExp(source, 'g');
|
|
1355
|
+
return function(string) {
|
|
1356
|
+
string = string == null ? '' : '' + string;
|
|
1357
|
+
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
|
|
1358
|
+
};
|
|
1359
|
+
};
|
|
1360
|
+
_.escape = createEscaper(escapeMap);
|
|
1361
|
+
_.unescape = createEscaper(unescapeMap);
|
|
1107
1362
|
|
|
1108
1363
|
// If the value of the named `property` is a function then invoke it with the
|
|
1109
1364
|
// `object` as context; otherwise, return it.
|
|
1110
|
-
_.result = function(object, property) {
|
|
1111
|
-
|
|
1112
|
-
|
|
1365
|
+
_.result = function(object, property, fallback) {
|
|
1366
|
+
var value = object == null ? void 0 : object[property];
|
|
1367
|
+
if (value === void 0) {
|
|
1368
|
+
value = fallback;
|
|
1369
|
+
}
|
|
1113
1370
|
return _.isFunction(value) ? value.call(object) : value;
|
|
1114
1371
|
};
|
|
1115
1372
|
|
|
1116
|
-
// Add your own custom functions to the Underscore object.
|
|
1117
|
-
_.mixin = function(obj) {
|
|
1118
|
-
each(_.functions(obj), function(name) {
|
|
1119
|
-
var func = _[name] = obj[name];
|
|
1120
|
-
_.prototype[name] = function() {
|
|
1121
|
-
var args = [this._wrapped];
|
|
1122
|
-
push.apply(args, arguments);
|
|
1123
|
-
return result.call(this, func.apply(_, args));
|
|
1124
|
-
};
|
|
1125
|
-
});
|
|
1126
|
-
};
|
|
1127
|
-
|
|
1128
1373
|
// Generate a unique integer id (unique within the entire client session).
|
|
1129
1374
|
// Useful for temporary DOM ids.
|
|
1130
1375
|
var idCounter = 0;
|
|
@@ -1153,22 +1398,26 @@
|
|
|
1153
1398
|
'\\': '\\',
|
|
1154
1399
|
'\r': 'r',
|
|
1155
1400
|
'\n': 'n',
|
|
1156
|
-
'\t': 't',
|
|
1157
1401
|
'\u2028': 'u2028',
|
|
1158
1402
|
'\u2029': 'u2029'
|
|
1159
1403
|
};
|
|
1160
1404
|
|
|
1161
|
-
var escaper = /\\|'|\r|\n|\
|
|
1405
|
+
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
|
|
1406
|
+
|
|
1407
|
+
var escapeChar = function(match) {
|
|
1408
|
+
return '\\' + escapes[match];
|
|
1409
|
+
};
|
|
1162
1410
|
|
|
1163
1411
|
// JavaScript micro-templating, similar to John Resig's implementation.
|
|
1164
1412
|
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
|
1165
1413
|
// and correctly escapes quotes within interpolated code.
|
|
1166
|
-
|
|
1167
|
-
|
|
1414
|
+
// NB: `oldSettings` only exists for backwards compatibility.
|
|
1415
|
+
_.template = function(text, settings, oldSettings) {
|
|
1416
|
+
if (!settings && oldSettings) settings = oldSettings;
|
|
1168
1417
|
settings = _.defaults({}, settings, _.templateSettings);
|
|
1169
1418
|
|
|
1170
1419
|
// Combine delimiters into one regular expression via alternation.
|
|
1171
|
-
var matcher =
|
|
1420
|
+
var matcher = RegExp([
|
|
1172
1421
|
(settings.escape || noMatch).source,
|
|
1173
1422
|
(settings.interpolate || noMatch).source,
|
|
1174
1423
|
(settings.evaluate || noMatch).source
|
|
@@ -1178,19 +1427,18 @@
|
|
|
1178
1427
|
var index = 0;
|
|
1179
1428
|
var source = "__p+='";
|
|
1180
1429
|
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
|
1181
|
-
source += text.slice(index, offset)
|
|
1182
|
-
|
|
1430
|
+
source += text.slice(index, offset).replace(escaper, escapeChar);
|
|
1431
|
+
index = offset + match.length;
|
|
1183
1432
|
|
|
1184
1433
|
if (escape) {
|
|
1185
1434
|
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
|
1186
|
-
}
|
|
1187
|
-
if (interpolate) {
|
|
1435
|
+
} else if (interpolate) {
|
|
1188
1436
|
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
|
1189
|
-
}
|
|
1190
|
-
if (evaluate) {
|
|
1437
|
+
} else if (evaluate) {
|
|
1191
1438
|
source += "';\n" + evaluate + "\n__p+='";
|
|
1192
1439
|
}
|
|
1193
|
-
|
|
1440
|
+
|
|
1441
|
+
// Adobe VMs need the match returned to produce the correct offest.
|
|
1194
1442
|
return match;
|
|
1195
1443
|
});
|
|
1196
1444
|
source += "';\n";
|
|
@@ -1200,29 +1448,31 @@
|
|
|
1200
1448
|
|
|
1201
1449
|
source = "var __t,__p='',__j=Array.prototype.join," +
|
|
1202
1450
|
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
|
1203
|
-
source +
|
|
1451
|
+
source + 'return __p;\n';
|
|
1204
1452
|
|
|
1205
1453
|
try {
|
|
1206
|
-
render = new Function(settings.variable || 'obj', '_', source);
|
|
1454
|
+
var render = new Function(settings.variable || 'obj', '_', source);
|
|
1207
1455
|
} catch (e) {
|
|
1208
1456
|
e.source = source;
|
|
1209
1457
|
throw e;
|
|
1210
1458
|
}
|
|
1211
1459
|
|
|
1212
|
-
if (data) return render(data, _);
|
|
1213
1460
|
var template = function(data) {
|
|
1214
1461
|
return render.call(this, data, _);
|
|
1215
1462
|
};
|
|
1216
1463
|
|
|
1217
|
-
// Provide the compiled
|
|
1218
|
-
|
|
1464
|
+
// Provide the compiled source as a convenience for precompilation.
|
|
1465
|
+
var argument = settings.variable || 'obj';
|
|
1466
|
+
template.source = 'function(' + argument + '){\n' + source + '}';
|
|
1219
1467
|
|
|
1220
1468
|
return template;
|
|
1221
1469
|
};
|
|
1222
1470
|
|
|
1223
|
-
// Add a "chain" function
|
|
1471
|
+
// Add a "chain" function. Start chaining a wrapped Underscore object.
|
|
1224
1472
|
_.chain = function(obj) {
|
|
1225
|
-
|
|
1473
|
+
var instance = _(obj);
|
|
1474
|
+
instance._chain = true;
|
|
1475
|
+
return instance;
|
|
1226
1476
|
};
|
|
1227
1477
|
|
|
1228
1478
|
// OOP
|
|
@@ -1232,45 +1482,67 @@
|
|
|
1232
1482
|
// underscore functions. Wrapped objects may be chained.
|
|
1233
1483
|
|
|
1234
1484
|
// Helper function to continue chaining intermediate results.
|
|
1235
|
-
var result = function(obj) {
|
|
1236
|
-
return
|
|
1485
|
+
var result = function(instance, obj) {
|
|
1486
|
+
return instance._chain ? _(obj).chain() : obj;
|
|
1487
|
+
};
|
|
1488
|
+
|
|
1489
|
+
// Add your own custom functions to the Underscore object.
|
|
1490
|
+
_.mixin = function(obj) {
|
|
1491
|
+
_.each(_.functions(obj), function(name) {
|
|
1492
|
+
var func = _[name] = obj[name];
|
|
1493
|
+
_.prototype[name] = function() {
|
|
1494
|
+
var args = [this._wrapped];
|
|
1495
|
+
push.apply(args, arguments);
|
|
1496
|
+
return result(this, func.apply(_, args));
|
|
1497
|
+
};
|
|
1498
|
+
});
|
|
1237
1499
|
};
|
|
1238
1500
|
|
|
1239
1501
|
// Add all of the Underscore functions to the wrapper object.
|
|
1240
1502
|
_.mixin(_);
|
|
1241
1503
|
|
|
1242
1504
|
// Add all mutator Array functions to the wrapper.
|
|
1243
|
-
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
|
1505
|
+
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
|
1244
1506
|
var method = ArrayProto[name];
|
|
1245
1507
|
_.prototype[name] = function() {
|
|
1246
1508
|
var obj = this._wrapped;
|
|
1247
1509
|
method.apply(obj, arguments);
|
|
1248
|
-
if ((name
|
|
1249
|
-
return result
|
|
1510
|
+
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
|
|
1511
|
+
return result(this, obj);
|
|
1250
1512
|
};
|
|
1251
1513
|
});
|
|
1252
1514
|
|
|
1253
1515
|
// Add all accessor Array functions to the wrapper.
|
|
1254
|
-
each(['concat', 'join', 'slice'], function(name) {
|
|
1516
|
+
_.each(['concat', 'join', 'slice'], function(name) {
|
|
1255
1517
|
var method = ArrayProto[name];
|
|
1256
1518
|
_.prototype[name] = function() {
|
|
1257
|
-
return result
|
|
1519
|
+
return result(this, method.apply(this._wrapped, arguments));
|
|
1258
1520
|
};
|
|
1259
1521
|
});
|
|
1260
1522
|
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
this._chain = true;
|
|
1266
|
-
return this;
|
|
1267
|
-
},
|
|
1523
|
+
// Extracts the result from a wrapped and chained object.
|
|
1524
|
+
_.prototype.value = function() {
|
|
1525
|
+
return this._wrapped;
|
|
1526
|
+
};
|
|
1268
1527
|
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
}
|
|
1528
|
+
// Provide unwrapping proxy for some methods used in engine operations
|
|
1529
|
+
// such as arithmetic and JSON stringification.
|
|
1530
|
+
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
|
|
1273
1531
|
|
|
1274
|
-
|
|
1532
|
+
_.prototype.toString = function() {
|
|
1533
|
+
return '' + this._wrapped;
|
|
1534
|
+
};
|
|
1275
1535
|
|
|
1276
|
-
|
|
1536
|
+
// AMD registration happens at the end for compatibility with AMD loaders
|
|
1537
|
+
// that may not enforce next-turn semantics on modules. Even though general
|
|
1538
|
+
// practice for AMD registration is to be anonymous, underscore registers
|
|
1539
|
+
// as a named module because, like jQuery, it is a base library that is
|
|
1540
|
+
// popular enough to be bundled in a third party lib, but not be part of
|
|
1541
|
+
// an AMD load request. Those cases could generate an error when an
|
|
1542
|
+
// anonymous define() is called outside of a loader request.
|
|
1543
|
+
if (typeof define === 'function' && define.amd) {
|
|
1544
|
+
define('underscore', [], function() {
|
|
1545
|
+
return _;
|
|
1546
|
+
});
|
|
1547
|
+
}
|
|
1548
|
+
}.call(this));
|