lodash.js 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977
  1. /*!
  2. * Lo-Dash v0.1.0 <https://github.com/bestiejs/lodash>
  3. * Copyright 2012 John-David Dalton <http://allyoucanleet.com/>
  4. * Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
  5. * <http://documentcloud.github.com/underscore>
  6. * Available under MIT license <http://mths.be/mit>
  7. */
  8. ;(function(window, undefined) {
  9. 'use strict';
  10. /** Used to escape characters in templates */
  11. var escapes = {
  12. '\\': '\\',
  13. "'": "'",
  14. '\n': 'n',
  15. '\r': 'r',
  16. '\t': 't',
  17. '\u2028': 'u2028',
  18. '\u2029': 'u2029'
  19. };
  20. /** Detect free variable `exports` */
  21. var freeExports = typeof exports == 'object' && exports &&
  22. (typeof global == 'object' && global && global == global.global && (window = global), exports);
  23. /** Used to generate unique IDs */
  24. var idCounter = 0;
  25. /** Used to restore the original `_` reference in `noConflict` */
  26. var oldDash = window._;
  27. /** Used to match tokens in template text */
  28. var reToken = /__token__(\d+)/g;
  29. /**
  30. * Used to match unescaped characters in template text
  31. * (older Safari can't parse unicode escape sequences in a RegExp literals)
  32. */
  33. var reUnescaped = RegExp('\\\\|[\'\\n\\r\\t\u2028\u2029]', 'g');
  34. /** Used to replace template delimiters */
  35. var token = '__token__';
  36. /** Used store tokenized template text code snippets */
  37. var tokenized = [];
  38. /** Object#toString result shortcuts */
  39. var arrayClass = '[object Array]',
  40. boolClass = '[object Boolean]',
  41. dateClass = '[object Date]',
  42. funcClass = '[object Function]',
  43. numberClass = '[object Number]',
  44. regexpClass = '[object RegExp]',
  45. stringClass = '[object String]';
  46. /** Native prototype shortcuts */
  47. var ArrayProto = Array.prototype,
  48. ObjProto = Object.prototype;
  49. /** Native method shortcuts */
  50. var concat = ArrayProto.concat,
  51. hasOwnProperty = ObjProto.hasOwnProperty,
  52. join = ArrayProto.join,
  53. push = ArrayProto.push,
  54. slice = ArrayProto.slice,
  55. toString = ObjProto.toString;
  56. /* Native method shortcuts for methods with the same name as other `lodash` methods */
  57. var nativeIsArray = Array.isArray,
  58. nativeIsFinite = window.isFinite,
  59. nativeKeys = Object.keys;
  60. /** Timer shortcuts */
  61. var clearTimeout = window.clearTimeout,
  62. setTimeout = window.setTimeout;
  63. /** Compilation options for `_.every` */
  64. var everyFactoryOptions = {
  65. 'init': 'true',
  66. 'inLoop': 'if (!callback(collection[index], index, collection)) return !result'
  67. };
  68. /** Compilation options for `_.extend` */
  69. var extendFactoryOptions = {
  70. 'args': 'object',
  71. 'init': 'object',
  72. 'top':
  73. 'for (var source, j = 1, length = arguments.length; j < length; j++) {\n' +
  74. 'source = arguments[j]',
  75. 'loopExp': 'index in source',
  76. 'useHas': false,
  77. 'inLoop': 'object[index] = source[index]',
  78. 'bottom': '}'
  79. };
  80. /** Compilation options for `_.filter` */
  81. var filterFactoryOptions = {
  82. 'init': '[]',
  83. 'inLoop': 'callback(collection[index], index, collection) && result.push(collection[index])'
  84. };
  85. /** Compilation options for `_.forEach` */
  86. var forEachFactoryOptions = {
  87. 'args': 'collection, callback, thisArg',
  88. 'init': 'collection',
  89. 'top':
  90. 'if (!callback) {\n' +
  91. 'callback = identity\n' +
  92. '}\n' +
  93. 'else if (thisArg) {\n' +
  94. 'callback = bind(callback, thisArg)\n' +
  95. '}',
  96. 'inLoop': 'callback(collection[index], index, collection)'
  97. };
  98. /** Compilation options for `_.map` */
  99. var mapFactoryOptions = {
  100. 'init': '',
  101. 'exit': 'if (!collection) return []',
  102. 'beforeLoop': {
  103. 'array': 'result = Array(length)',
  104. 'object': 'result = []'
  105. },
  106. 'inLoop': {
  107. 'array': 'result[index] = callback(collection[index], index, collection)',
  108. 'object': 'result.push(callback(collection[index], index, collection))'
  109. }
  110. };
  111. /** Compilation options for `_.max` */
  112. var maxFactoryOptions = {
  113. 'top':
  114. 'var current, computed = -Infinity, result = computed;\n' +
  115. 'if (!callback) {\n' +
  116. 'if (isArray(collection) && collection[0] === +collection[0])' +
  117. 'return Math.max.apply(Math, collection);\n' +
  118. 'if (isEmpty(collection))' +
  119. 'return result\n' +
  120. '} else if (thisArg) callback = bind(callback, thisArg)',
  121. 'inLoop':
  122. 'current = callback' +
  123. '? callback(collection[index], index, collection)' +
  124. ': collection[index];\n' +
  125. 'if (current >= computed)' +
  126. 'computed = current, result = collection[index]'
  127. };
  128. /*--------------------------------------------------------------------------*/
  129. /**
  130. * The `lodash` function.
  131. *
  132. * @name _
  133. * @constructor
  134. * @param {Mixed} value The value to wrap in a `Lodash` instance.
  135. * @returns {Object} Returns a `Lodash` instance.
  136. */
  137. function lodash(value) {
  138. // allow invoking `lodash` without the `new` operator
  139. return new Lodash(value);
  140. }
  141. /**
  142. * Creates a `Lodash` instance that wraps a value to allow chaining.
  143. *
  144. * @private
  145. * @constructor
  146. * @param {Mixed} value The value to wrap.
  147. */
  148. function Lodash(value) {
  149. this._wrapped = value;
  150. }
  151. /*--------------------------------------------------------------------------*/
  152. /**
  153. * Checks if a `value` is an array.
  154. *
  155. * @static
  156. * @memberOf _
  157. * @category Objects
  158. * @param {Mixed} value The value to check.
  159. * @returns {Boolean} Returns `true` if the `value` is an array, else `false`.
  160. * @example
  161. *
  162. * (function() { return _.isArray(arguments); })();
  163. * // => false
  164. *
  165. * _.isArray([1, 2, 3]);
  166. * // => true
  167. */
  168. var isArray = nativeIsArray || function(value) {
  169. return toString.call(value) == arrayClass;
  170. };
  171. /**
  172. * Checks if a `value` is empty. Arrays or strings with a length of `0` and
  173. * objects with no enumerable own properties are considered "empty".
  174. *
  175. * @static
  176. * @memberOf _
  177. * @category Objects
  178. * @param {Mixed} value The value to check.
  179. * @returns {Boolean} Returns `true` if the `value` is empty, else `false`.
  180. * @example
  181. *
  182. * _.isEmpty([1, 2, 3]);
  183. * // => false
  184. *
  185. * _.isEmpty({});
  186. * // => true
  187. */
  188. var isEmpty = iterationFactory({
  189. 'args': 'value',
  190. 'iterate': 'objects',
  191. 'init': 'true',
  192. 'top':
  193. 'var className = toString.call(value);\n' +
  194. 'if (className == arrayClass || className == stringClass) return !value.length',
  195. 'inLoop': 'return false'
  196. });
  197. /*--------------------------------------------------------------------------*/
  198. /**
  199. * Used by `template()` to replace tokens with their corresponding code snippets.
  200. *
  201. * @private
  202. * @param {String} match The matched token.
  203. * @param {String} index The `tokenized` index of the code snippet.
  204. * @returns {String} Returns the code snippet.
  205. */
  206. function detokenize(match, index) {
  207. return tokenized[index];
  208. }
  209. /**
  210. * Used by `template()` to escape characters for inclusion in compiled
  211. * string literals.
  212. *
  213. * @private
  214. * @param {String} match The matched character to escape.
  215. * @returns {String} Returns the escaped character.
  216. */
  217. function escapeChar(match) {
  218. return '\\' + escapes[match];
  219. }
  220. /**
  221. * Compiles iteration functions.
  222. *
  223. * @private
  224. * @param {Object} [options1, options2, ..] The compile options objects.
  225. * @returns {Function} Returns the compiled function.
  226. */
  227. function iterationFactory() {
  228. var prop,
  229. index = -1,
  230. array = {},
  231. object = {},
  232. options = {},
  233. props = ['beforeLoop', 'loopExp', 'inLoop'];
  234. // use simple loops to merge options because `extend` isn't defined yet
  235. while (++index < arguments.length) {
  236. for (prop in arguments[index]) {
  237. options[prop] = arguments[index][prop];
  238. }
  239. }
  240. // assign the `array` and `object` branch options
  241. while ((prop = props.pop())) {
  242. if (typeof options[prop] == 'object') {
  243. array[prop] = options[prop].array;
  244. object[prop] = options[prop].object;
  245. } else {
  246. array[prop] = object[prop] = options[prop] || '';
  247. }
  248. }
  249. var args = options.args,
  250. firstArg = /^[^,]+/.exec(args)[0],
  251. init = options.init,
  252. iterate = options.iterate,
  253. arrayBranch = !(firstArg == 'object' || iterate == 'objects'),
  254. objectBranch = !(firstArg == 'array' || iterate == 'arrays'),
  255. useHas = options.useHas !== false;
  256. // all strings used to compile methods are minified during the build process
  257. return Function('arrayClass, bind, concat, funcClass, hasOwnProperty, identity,' +
  258. 'indexOf, Infinity, isArray, isEmpty, Math, slice, stringClass,' +
  259. 'toString, undefined',
  260. // compile the function in strict mode
  261. '"use strict";' +
  262. // compile the arguments the function accepts
  263. 'return function(' + args + ') {\n' +
  264. // assign the `result` variable an initial value
  265. ('var index, result' + (init ? '=' + init : '')) + ';\n' +
  266. // add code to exit early or do so if the first argument is falsey
  267. (options.exit || 'if (!' + firstArg + ') return result') + ';\n' +
  268. // add code after the exit snippet but before the iteration branches
  269. (options.top || '') + ';\n' +
  270. // the following branch is for iterating arrays and array-like objects
  271. (arrayBranch
  272. // initialize `length` and `index` variables
  273. ? 'var length = ' + firstArg + '.length;\n' +
  274. 'index = -1;\n' +
  275. // check if the `collection` is array-like when there is an object iteration branch
  276. ((objectBranch ? 'if (length === +length) {\n' : '') +
  277. // add code before the while-loop
  278. (array.beforeLoop || '') + ';\n' +
  279. // add a custom loop expression
  280. 'while (' + (array.loopExp || '++index < length') + ') {\n' +
  281. // add code inside the while-loop
  282. array.inLoop +
  283. '\n}' +
  284. // end the array-like if-statement
  285. (objectBranch ? '\n}\n' : ''))
  286. : ''
  287. ) +
  288. // the following branch is for iterating an object's own/inherited properties
  289. (objectBranch
  290. // begin the else-statement when there is an array-like iteration branch
  291. ? ((arrayBranch ? 'else {\n' : '') +
  292. // add code before the for-in loop
  293. (object.beforeLoop || '') + ';\n' +
  294. // add a custom loop expression
  295. 'for (' + (object.loopExp || 'index in ' + firstArg) + ') {\n' +
  296. // compile in `hasOwnProperty` checks when `options.useHas` is not `false`
  297. (useHas ? 'if (hasOwnProperty.call(' + /\S+$/.exec(object.loopExp || firstArg)[0] + ',index)) {\n' : '') +
  298. // add code inside the for-in loop
  299. object.inLoop +
  300. (useHas ? '\n}' : '') +
  301. '\n}' +
  302. // end the object iteration else-statement
  303. (arrayBranch ? '\n}\n' : ''))
  304. : ''
  305. ) +
  306. // add code to the bottom of the iteration method
  307. (options.bottom || '') + ';\n' +
  308. // finally, return the `result`
  309. 'return result' +
  310. '\n}'
  311. )(arrayClass, bind, concat, funcClass, hasOwnProperty, identity,
  312. indexOf, Infinity, isArray, isEmpty, Math, slice, stringClass, toString);
  313. }
  314. /**
  315. * Used by `template()` to replace "escape" template delimiters with tokens.
  316. *
  317. * @private
  318. * @param {String} match The matched template delimiter.
  319. * @param {String} value The delimiter value.
  320. * @returns {String} Returns a token.
  321. */
  322. function tokenizeEscape(match, value) {
  323. var index = tokenized.length;
  324. tokenized[index] = "'+\n((__t = (" + value + ")) == null ? '' : __e(__t)) +\n'";
  325. return token + index;
  326. }
  327. /**
  328. * Used by `template()` to replace "interpolate" template delimiters with tokens.
  329. *
  330. * @private
  331. * @param {String} match The matched template delimiter.
  332. * @param {String} value The delimiter value.
  333. * @returns {String} Returns a token.
  334. */
  335. function tokenizeInterpolate(match, value) {
  336. var index = tokenized.length;
  337. tokenized[index] = "'+\n((__t = (" + value + ")) == null ? '' : __t) +\n'";
  338. return token + index;
  339. }
  340. /**
  341. * Used by `template()` to replace "evaluate" template delimiters with tokens.
  342. *
  343. * @private
  344. * @param {String} match The matched template delimiter.
  345. * @param {String} value The delimiter value.
  346. * @returns {String} Returns a token.
  347. */
  348. function tokenizeEvaluate(match, value) {
  349. var index = tokenized.length;
  350. tokenized[index] = "';\n" + value + ";\n__p += '";
  351. return token + index;
  352. }
  353. /*--------------------------------------------------------------------------*/
  354. /**
  355. * Checks if a given `target` value is present in a `collection` using strict
  356. * equality for comparisons, i.e. `===`.
  357. *
  358. * @static
  359. * @memberOf _
  360. * @alias include
  361. * @category Collections
  362. * @param {Array|Object} collection The collection to iterate over.
  363. * @param {Mixed} target The value to check for.
  364. * @returns {Boolean} Returns `true` if `target` value is found, else `false`.
  365. * @example
  366. *
  367. * _.contains([1, 2, 3], 3);
  368. * // => true
  369. */
  370. var contains = iterationFactory({
  371. 'args': 'collection, target',
  372. 'init': 'false',
  373. 'inLoop': 'if (collection[index] === target) return true'
  374. });
  375. /**
  376. * Checks if the `callback` returns a truthy value for **all** elements of a
  377. * `collection`. The `callback` is invoked with 3 arguments; for arrays they
  378. * are (value, index, array) and for objects they are (value, key, object).
  379. *
  380. * @static
  381. * @memberOf _
  382. * @alias all
  383. * @category Collections
  384. * @param {Array|Object} collection The collection to iterate over.
  385. * @param {Function} callback The function called per iteration.
  386. * @param {Mixed} [thisArg] The `this` binding for the callback.
  387. * @returns {Boolean} Returns `true` if all values pass the callback check, else `false`.
  388. * @example
  389. *
  390. * _.every([true, 1, null, 'yes'], Boolean);
  391. * => false
  392. */
  393. var every = iterationFactory(forEachFactoryOptions, everyFactoryOptions);
  394. /**
  395. * Examines each value in a `collection`, returning an array of all values the
  396. * `callback` returns truthy for. The `callback` is invoked with 3 arguments;
  397. * for arrays they are (value, index, array) and for objects they are
  398. * (value, key, object).
  399. *
  400. * @static
  401. * @memberOf _
  402. * @alias select
  403. * @category Collections
  404. * @param {Array|Object} collection The collection to iterate over.
  405. * @param {Function} callback The function called per iteration.
  406. * @param {Mixed} [thisArg] The `this` binding for the callback.
  407. * @returns {Array} Returns a new array of values that passed callback check.
  408. * @example
  409. *
  410. * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
  411. * // => [2, 4, 6]
  412. */
  413. var filter = iterationFactory(forEachFactoryOptions, filterFactoryOptions);
  414. /**
  415. * Examines each value in a `collection`, returning the first one the `callback`
  416. * returns truthy for. The function returns as soon as it finds an acceptable
  417. * value, and does not iterate over the entire `collection`. The `callback` is
  418. * invoked with 3 arguments; for arrays they are (value, index, array) and for
  419. * objects they are (value, key, object).
  420. *
  421. * @static
  422. * @memberOf _
  423. * @alias detect
  424. * @category Collections
  425. * @param {Array|Object} collection The collection to iterate over.
  426. * @param {Function} callback The function called per iteration.
  427. * @param {Mixed} [thisArg] The `this` binding for the callback.
  428. * @returns {Mixed} Returns the value that passed the callback check, else `undefined`.
  429. * @example
  430. *
  431. * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
  432. * // => 2
  433. */
  434. var find = iterationFactory(forEachFactoryOptions, {
  435. 'inLoop': 'if (callback(collection[index], index, collection)) return collection[index]'
  436. });
  437. /**
  438. * Iterates over a `collection`, executing the `callback` for each value in the
  439. * `collection`. The `callback` is bound to the `thisArg` value, if one is passed.
  440. * The `callback` is invoked with 3 arguments; for arrays they are
  441. * (value, index, array) and for objects they are (value, key, object).
  442. *
  443. * @static
  444. * @memberOf _
  445. * @alias each
  446. * @category Collections
  447. * @param {Array|Object} collection The collection to iterate over.
  448. * @param {Function} callback The function called per iteration.
  449. * @param {Mixed} [thisArg] The `this` binding for the callback.
  450. * @returns {Array|Object} Returns the `collection`.
  451. * @example
  452. *
  453. * _.forEach([1, 2, 3], function(num) { alert(num); });
  454. * // => alerts each number in turn...
  455. *
  456. * _.forEach({ 'one': 1, 'two': 2, 'three': 3}, function(num) { alert(num); });
  457. * // => alerts each number in turn...
  458. */
  459. var forEach = iterationFactory(forEachFactoryOptions);
  460. /**
  461. * Splits a `collection` into sets, grouped by the result of running each value
  462. * through `callback`. The `callback` is invoked with 3 arguments; for arrays
  463. * they are (value, index, array) and for objects they are (value, key, object).
  464. * The `callback` argument may also be the name of a property to group by.
  465. *
  466. * @static
  467. * @memberOf _
  468. * @category Collections
  469. * @param {Array|Object} collection The collection to iterate over.
  470. * @param {Function|String} callback The function called per iteration or
  471. * property name to group by.
  472. * @param {Mixed} [thisArg] The `this` binding for the callback.
  473. * @returns {Object} Returns an object of grouped values.
  474. * @example
  475. *
  476. * _.groupBy([1.3, 2.1, 2.4], function(num) { return Math.floor(num); });
  477. * // => { '1': [1.3], '2': [2.1, 2.4] }
  478. *
  479. * _.groupBy(['one', 'two', 'three'], 'length');
  480. * // => { '3': ['one', 'two'], '5': ['three'] }
  481. */
  482. var groupBy = iterationFactory(forEachFactoryOptions, {
  483. 'init': '{}',
  484. 'top':
  485. 'var prop, isFunc = toString.call(callback) == funcClass;\n' +
  486. 'if (isFunc && thisArg) callback = bind(callback, thisArg)',
  487. 'inLoop':
  488. 'prop = isFunc' +
  489. '? callback(collection[index], index, collection)' +
  490. ': collection[index][callback];\n' +
  491. '(result[prop] || (result[prop] = [])).push(collection[index])'
  492. });
  493. /**
  494. * Produces a new array of values by mapping each value in the `collection`
  495. * through a transformation `callback`. The `callback` is bound to the `thisArg`
  496. * value, if one is passed. The `callback` is invoked with 3 arguments; for
  497. * arrays they are (value, index, array) and for objects they are (value, key, object).
  498. *
  499. * @static
  500. * @memberOf _
  501. * @alias collect
  502. * @category Collections
  503. * @param {Array|Object} collection The collection to iterate over.
  504. * @param {Function} callback The function called per iteration.
  505. * @param {Mixed} [thisArg] The `this` binding for the callback.
  506. * @returns {Array} Returns a new array of values returned by the callback.
  507. * @example
  508. *
  509. * _.map([1, 2, 3], function(num) { return num * 3; });
  510. * // => [3, 6, 9]
  511. *
  512. * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
  513. * // => [3, 6, 9]
  514. */
  515. var map = iterationFactory(forEachFactoryOptions, mapFactoryOptions);
  516. /**
  517. * Retrieves the maximum value of a `collection`. If `callback` is passed,
  518. * it will be executed for each value in the `collection` to generate the
  519. * criterion by which the value is ranked. The `callback` is invoked with 3
  520. * arguments; for arrays they are (value, index, array) and for objects they
  521. * are (value, key, object).
  522. *
  523. * @static
  524. * @memberOf _
  525. * @category Collections
  526. * @param {Array|Object} collection The collection to iterate over.
  527. * @param {Function} [callback] The function called per iteration.
  528. * @param {Mixed} [thisArg] The `this` binding for the callback.
  529. * @returns {Mixed} Returns the maximum value.
  530. * @example
  531. *
  532. * var stooges = [
  533. * { 'name': 'moe', 'age': 40 },
  534. * { 'name': 'larry', 'age': 50 },
  535. * { 'name': 'curly', 'age': 60 }
  536. * ];
  537. *
  538. * _.max(stooges, function(stooge) { return stooge.age; });
  539. * // => { 'name': 'curly', 'age': 60 };
  540. */
  541. var max = iterationFactory(forEachFactoryOptions, maxFactoryOptions);
  542. /**
  543. * Retrieves the minimum value of a `collection`. If `callback` is passed,
  544. * it will be executed for each value in the `collection` to generate the
  545. * criterion by which the value is ranked. The `callback` is invoked with 3
  546. * arguments; for arrays they are (value, index, array) and for objects they
  547. * are (value, key, object).
  548. *
  549. * @static
  550. * @memberOf _
  551. * @category Collections
  552. * @param {Array|Object} collection The collection to iterate over.
  553. * @param {Function} [callback] The function called per iteration.
  554. * @param {Mixed} [thisArg] The `this` binding for the callback.
  555. * @returns {Mixed} Returns the minimum value.
  556. * @example
  557. *
  558. * _.min([10, 5, 100, 2, 1000]);
  559. * // => 2
  560. */
  561. var min = iterationFactory(forEachFactoryOptions, maxFactoryOptions, {
  562. 'top': maxFactoryOptions.top.replace('-', '').replace('max', 'min'),
  563. 'inLoop': maxFactoryOptions.inLoop.replace('>=', '<')
  564. });
  565. /**
  566. * Retrieves the value of a specified property from all values in a `collection`.
  567. *
  568. * @static
  569. * @memberOf _
  570. * @category Collections
  571. * @param {Array|Object} collection The collection to iterate over.
  572. * @param {String} property The property to pluck.
  573. * @returns {Array} Returns a new array of property values.
  574. * @example
  575. *
  576. * var stooges = [
  577. * { 'name': 'moe', 'age': 40 },
  578. * { 'name': 'larry', 'age': 50 },
  579. * { 'name': 'curly', 'age': 60 }
  580. * ];
  581. *
  582. * _.pluck(stooges, 'name');
  583. * // => ['moe', 'larry', 'curly']
  584. */
  585. var pluck = iterationFactory(mapFactoryOptions, {
  586. 'args': 'collection, property',
  587. 'inLoop': {
  588. 'array': 'result[index] = collection[index][property]',
  589. 'object': 'result.push(collection[index][property])'
  590. }
  591. });
  592. /**
  593. * Boils down a `collection` to a single value. The initial state of the
  594. * reduction is `accumulator` and each successive step of it should be returned
  595. * by the `callback`. The `callback` is bound to the `thisArg` value, if one is
  596. * passed. The `callback` is invoked with 4 arguments; for arrays they are
  597. * (accumulator, value, index, array) and for objects they are
  598. * (accumulator, value, key, object).
  599. *
  600. * @static
  601. * @memberOf _
  602. * @alias foldl, inject
  603. * @category Collections
  604. * @param {Array|Object} collection The collection to iterate over.
  605. * @param {Function} callback The function called per iteration.
  606. * @param {Mixed} [accumulator] Initial value of the accumulator.
  607. * @param {Mixed} [thisArg] The `this` binding for the callback.
  608. * @returns {Mixed} Returns the accumulated value.
  609. * @example
  610. *
  611. * var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; });
  612. * // => 6
  613. */
  614. var reduce = iterationFactory({
  615. 'args': 'collection, callback, accumulator, thisArg',
  616. 'init': 'accumulator',
  617. 'top':
  618. 'var noaccum = arguments.length < 3;\n' +
  619. 'if (thisArg) callback = bind(callback, thisArg)',
  620. 'beforeLoop': {
  621. 'array': 'if (noaccum) result = collection[++index]'
  622. },
  623. 'inLoop': {
  624. 'array':
  625. 'result = callback(result, collection[index], index, collection)',
  626. 'object':
  627. 'result = noaccum\n' +
  628. '? (noaccum = false, collection[index])\n' +
  629. ': callback(result, collection[index], index, collection)'
  630. }
  631. });
  632. /**
  633. * The right-associative version of `_.reduce`. The `callback` is bound to the
  634. * `thisArg` value, if one is passed. The `callback` is invoked with 4 arguments;
  635. * for arrays they are (accumulator, value, index, array) and for objects they
  636. * are (accumulator, value, key, object).
  637. *
  638. * @static
  639. * @memberOf _
  640. * @alias foldr
  641. * @category Collections
  642. * @param {Array|Object} collection The collection to iterate over.
  643. * @param {Function} callback The function called per iteration.
  644. * @param {Mixed} [accumulator] Initial value of the accumulator.
  645. * @param {Mixed} [thisArg] The `this` binding for the callback.
  646. * @returns {Mixed} Returns the accumulated value.
  647. * @example
  648. *
  649. * var list = [[0, 1], [2, 3], [4, 5]];
  650. * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
  651. * // => [4, 5, 2, 3, 0, 1]
  652. */
  653. function reduceRight(collection, callback, accumulator, thisArg) {
  654. if (!collection) {
  655. return accumulator;
  656. }
  657. var length = collection.length,
  658. noaccum = arguments.length < 3;
  659. if(thisArg) {
  660. callback = bind(callback, thisArg);
  661. }
  662. if (length === +length) {
  663. if (length && noaccum) {
  664. accumulator = collection[--length];
  665. }
  666. while (length--) {
  667. accumulator = callback(accumulator, collection[length], length, collection);
  668. }
  669. return accumulator;
  670. }
  671. var prop,
  672. props = keys(collection);
  673. length = props.length;
  674. if (length && noaccum) {
  675. accumulator = collection[props[--length]];
  676. }
  677. while (length--) {
  678. prop = props[length];
  679. accumulator = callback(accumulator, collection[prop], prop, collection);
  680. }
  681. return accumulator;
  682. }
  683. /**
  684. * The opposite of `_.filter`, this method returns the values of a `collection`
  685. * that `callback` does **not** return truthy for. The `callback` is invoked
  686. * with 3 arguments; for arrays they are (value, index, array) and for objects
  687. * they are (value, key, object).
  688. *
  689. * @static
  690. * @memberOf _
  691. * @category Collections
  692. * @param {Array|Object} collection The collection to iterate over.
  693. * @param {Function} callback The function called per iteration.
  694. * @param {Mixed} [thisArg] The `this` binding for the callback.
  695. * @returns {Array} Returns a new array of values that did **not** pass the callback check.
  696. * @example
  697. *
  698. * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
  699. * // => [1, 3, 5]
  700. */
  701. var reject = iterationFactory(forEachFactoryOptions, filterFactoryOptions, {
  702. 'inLoop': '!' + filterFactoryOptions.inLoop
  703. });
  704. /**
  705. * Gets the number of values in the `collection`.
  706. *
  707. * @static
  708. * @memberOf _
  709. * @category Collections
  710. * @param {Array|Object} collection The collection inspect.
  711. * @returns {Number} Returns the number of values in the collection.
  712. * @example
  713. *
  714. * _.size({ 'one': 1, 'two': 2, 'three': 3 });
  715. * // => 3
  716. */
  717. function size(collection) {
  718. var className = toString.call(collection);
  719. return className == arrayClass || className == stringClass
  720. ? collection.length
  721. : keys(collection).length;
  722. }
  723. /**
  724. * Produces a new sorted array, ranked in ascending order by the results of
  725. * running each value of a `collection` through `callback`. The `callback` is
  726. * invoked with 3 arguments; for arrays they are (value, index, array) and for
  727. * objects they are (value, key, object). The `callback` argument may also be
  728. * the name of a property to sort by (e.g. 'length').
  729. *
  730. * @static
  731. * @memberOf _
  732. * @category Collections
  733. * @param {Array|Object} collection The collection to iterate over.
  734. * @param {Function|String} callback The function called per iteration or
  735. * property name to sort by.
  736. * @param {Mixed} [thisArg] The `this` binding for the callback.
  737. * @returns {Array} Returns a new array of sorted values.
  738. * @example
  739. *
  740. * _.sortBy([1, 2, 3, 4, 5, 6], function(num) { return Math.sin(num); });
  741. * // => [5, 4, 6, 3, 1, 2]
  742. */
  743. function sortBy(collection, callback, thisArg) {
  744. if (toString.call(callback) != funcClass) {
  745. var prop = callback;
  746. callback = function(collection) { return collection[prop]; };
  747. } else if (thisArg) {
  748. callback = bind(callback, thisArg);
  749. }
  750. return pluck(map(collection, function(value, index) {
  751. return {
  752. 'criteria': callback(value, index, collection),
  753. 'value': value
  754. };
  755. }).sort(function(left, right) {
  756. var a = left.criteria,
  757. b = right.criteria;
  758. if (a === undefined) {
  759. return 1;
  760. }
  761. if (b === undefined) {
  762. return -1;
  763. }
  764. return a < b ? -1 : a > b ? 1 : 0;
  765. }), 'value');
  766. }
  767. /**
  768. * Checks if the `callback` returns a truthy value for **any** element of a
  769. * `collection`. The function returns as soon as it finds passing value, and
  770. * does not iterate over the entire `collection`. The `callback` is invoked
  771. * with 3 arguments; for arrays they are (value, index, array) and for objects
  772. * they are (value, key, object).
  773. *
  774. * @static
  775. * @memberOf _
  776. * @alias any
  777. * @category Collections
  778. * @param {Array|Object} collection The collection to iterate over.
  779. * @param {Function} callback The function called per iteration.
  780. * @param {Mixed} [thisArg] The `this` binding for the callback.
  781. * @returns {Boolean} Returns `true` if any value passes the callback check, else `false`.
  782. * @example
  783. *
  784. * _.some([null, 0, 'yes', false]);
  785. * // => true
  786. */
  787. var some = iterationFactory(forEachFactoryOptions, everyFactoryOptions, {
  788. 'init': 'false',
  789. 'inLoop': everyFactoryOptions.inLoop.replace('!', '')
  790. });
  791. /**
  792. * Converts the `collection`, into an array. Useful for converting the
  793. * `arguments` object.
  794. *
  795. * @static
  796. * @memberOf _
  797. * @category Collections
  798. * @param {Array|Object} collection The collection to convert.
  799. * @returns {Array} Returns the new converted array.
  800. * @example
  801. *
  802. * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
  803. * // => [2, 3, 4]
  804. */
  805. function toArray(collection) {
  806. if (!collection) {
  807. return [];
  808. }
  809. if (toString.call(collection.toArray) == funcClass) {
  810. return collection.toArray();
  811. }
  812. var length = collection.length;
  813. if (length === +length) {
  814. return slice.call(collection);
  815. }
  816. return values(collection);
  817. }
  818. /**
  819. * Produces an array of enumerable own property values of the `collection`.
  820. *
  821. * @static
  822. * @memberOf _
  823. * @alias methods
  824. * @category Collections
  825. * @param {Array|Object} collection The collection to inspect.
  826. * @returns {Array} Returns a new array of property values.
  827. * @example
  828. *
  829. * _.values({ 'one': 1, 'two': 2, 'three': 3 });
  830. * // => [1, 2, 3]
  831. */
  832. var values = iterationFactory(mapFactoryOptions, {
  833. 'args': 'collection',
  834. 'inLoop': {
  835. 'array': 'result[index] = collection[index]',
  836. 'object': 'result.push(collection[index])'
  837. }
  838. });
  839. /*--------------------------------------------------------------------------*/
  840. /**
  841. * Produces a new array with all falsey values of `array` removed. The values
  842. * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey.
  843. *
  844. * @static
  845. * @memberOf _
  846. * @category Arrays
  847. * @param {Array} array The array to compact.
  848. * @returns {Array} Returns a new filtered array.
  849. * @example
  850. *
  851. * _.compact([0, 1, false, 2, '', 3]);
  852. * // => [1, 2, 3]
  853. */
  854. var compact = function(array) {
  855. var index = -1,
  856. length = array.length,
  857. result = [];
  858. while (++index < length) {
  859. if (array[index]) {
  860. result.push(array[index]);
  861. }
  862. }
  863. return result;
  864. }
  865. /**
  866. * Produces a new array of `array` values not present in the other arrays
  867. * using strict equality for comparisons, i.e. `===`.
  868. *
  869. * @static
  870. * @memberOf _
  871. * @category Arrays
  872. * @param {Array} array The array to process.
  873. * @param {Mixed} [array1, array2, ...] Arrays to check.
  874. * @returns {Array} Returns a new array of `array` values not present in the
  875. * other arrays.
  876. * @example
  877. *
  878. * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
  879. * // => [1, 3, 4]
  880. */
  881. function difference(array) {
  882. var index = -1,
  883. length = array.length,
  884. result = [],
  885. flattened = concat.apply(result, slice.call(arguments, 1));
  886. while (++index < length) {
  887. if (indexOf(flattened, array[index]) < 0) {
  888. result.push(array[index]);
  889. }
  890. }
  891. return result;
  892. }
  893. /**
  894. * Gets the first value of the `array`. Pass `n` to return the first `n` values
  895. * of the `array`.
  896. *
  897. * @static
  898. * @memberOf _
  899. * @alias head, take
  900. * @category Arrays
  901. * @param {Array} array The array to query.
  902. * @param {Number} [n] The number of elements to return.
  903. * @param {Object} [guard] Internally used to allow this method to work with
  904. * others like `_.map` without using their callback `index` argument for `n`.
  905. * @returns {Mixed} Returns the first value or an array of the first `n` values
  906. * of the `array`.
  907. * @example
  908. *
  909. * _.first([5, 4, 3, 2, 1]);
  910. * // => 5
  911. */
  912. function first(array, n, guard) {
  913. return (n == undefined || guard) ? array[0] : slice.call(array, 0, n);
  914. }
  915. /**
  916. * Flattens a nested array (the nesting can be to any depth). If `shallow` is
  917. * truthy, `array` will only be flattened a single level.
  918. *
  919. * @static
  920. * @memberOf _
  921. * @category Arrays
  922. * @param {Array} array The array to compact.
  923. * @param {Boolean} shallow A flag to indicate only flattening a single level.
  924. * @returns {Array} Returns a new flattened array.
  925. * @example
  926. *
  927. * _.flatten([1, [2], [3, [[4]]]]);
  928. * // => [1, 2, 3, 4];
  929. *
  930. * _.flatten([1, [2], [3, [[4]]]], true);
  931. * // => [1, 2, 3, [[4]]];
  932. */
  933. function flatten(array, shallow) {
  934. if (shallow) {
  935. return concat.apply(ArrayProto, array);
  936. }
  937. var value,
  938. index = -1,
  939. length = array.length,
  940. result = [];
  941. while (++index < length) {
  942. value = array[index];
  943. if (isArray(value)) {
  944. push.apply(result, flatten(value));
  945. } else {
  946. result.push(value);
  947. }
  948. }
  949. return result;
  950. }
  951. /**
  952. * Gets the index at which the first occurrence of `value` is found using
  953. * strict equality for comparisons, i.e. `===`. If the `array` is already
  954. * sorted, passing `true` for `isSorted` will run a faster binary search.
  955. *
  956. * @static
  957. * @memberOf _
  958. * @category Arrays
  959. * @param {Array} array The array to search.
  960. * @param {Mixed} value The value to search for.
  961. * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
  962. * @returns {Number} Returns the index of the matched value or `-1`.
  963. * @example
  964. *
  965. * _.indexOf([1, 2, 3], 2);
  966. * // => 1
  967. */
  968. function indexOf(array, value, isSorted) {
  969. var index, length;
  970. if (!array) {
  971. return -1;
  972. }
  973. if (isSorted) {
  974. index = sortedIndex(array, value);
  975. return array[index] === value ? index : -1;
  976. }
  977. for (index = 0, length = array.length; index < length; index++) {
  978. if (array[index] === value) {
  979. return index;
  980. }
  981. }
  982. return -1;
  983. }
  984. /**
  985. * Gets all but the last value of the `array`. Pass `n` to exclude the last `n`
  986. * values from the result.
  987. *
  988. * @static
  989. * @memberOf _
  990. * @category Arrays
  991. * @param {Array} array The array to query.
  992. * @param {Number} [n] The number of elements to return.
  993. * @param {Object} [guard] Internally used to allow this method to work with
  994. * others like `_.map` without using their callback `index` argument for `n`.
  995. * @returns {Array} Returns all but the last value or `n` values of the `array`.
  996. * @example
  997. *
  998. * _.initial([5, 4, 3, 2, 1]);
  999. * // => [5, 4, 3, 2]
  1000. */
  1001. function initial(array, n, guard) {
  1002. return slice.call(array, 0, -((n == undefined || guard) ? 1 : n));
  1003. }
  1004. /**
  1005. * Computes the intersection of all the passed-in arrays.
  1006. *
  1007. * @static
  1008. * @memberOf _
  1009. * @alias intersect
  1010. * @category Arrays
  1011. * @param {Mixed} [array1, array2, ...] Arrays to process.
  1012. * @returns {Array} Returns a new array of unique values, in order, that are
  1013. * present in **all** of the arrays.
  1014. * @example
  1015. *
  1016. * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
  1017. * // => [1, 2]
  1018. */
  1019. function intersection(array) {
  1020. var value,
  1021. index = -1,
  1022. length = array.length,
  1023. others = slice.call(arguments, 1),
  1024. result = [];
  1025. while (++index < length) {
  1026. value = array[index];
  1027. if (indexOf(result, value) < 0 &&
  1028. every(others, function(other) { return indexOf(other, value) > -1; })) {
  1029. result.push(value);
  1030. }
  1031. }
  1032. return result;
  1033. }
  1034. /**
  1035. * Calls the method named by `methodName` for each value of the `collection`.
  1036. * Additional arguments will be passed to each invoked method.
  1037. *
  1038. * @static
  1039. * @memberOf _
  1040. * @category Arrays
  1041. * @param {Array} array The array to iterate over.
  1042. * @param {String} methodName The name of the method to invoke.
  1043. * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
  1044. * @returns {Array} Returns a new array of values returned from each invoked method.
  1045. * @example
  1046. *
  1047. * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
  1048. * // => [[1, 5, 7], [1, 2, 3]]
  1049. */
  1050. function invoke(array, methodName) {
  1051. var args = slice.call(arguments, 2),
  1052. index = -1,
  1053. length = array.length,
  1054. isFunc = toString.call(methodName) == funcClass,
  1055. result = [];
  1056. while (++index < length) {
  1057. result[index] = (isFunc ? methodName : array[index][methodName]).apply(array[index], args);
  1058. }
  1059. return result;
  1060. }
  1061. /**
  1062. * Gets the last value of the `array`. Pass `n` to return the lasy `n` values
  1063. * of the `array`.
  1064. *
  1065. * @static
  1066. * @memberOf _
  1067. * @category Arrays
  1068. * @param {Array} array The array to query.
  1069. * @param {Number} [n] The number of elements to return.
  1070. * @param {Object} [guard] Internally used to allow this method to work with
  1071. * others like `_.map` without using their callback `index` argument for `n`.
  1072. * @returns {Array} Returns all but the last value or `n` values of the `array`.
  1073. * @example
  1074. *
  1075. * _.last([5, 4, 3, 2, 1]);
  1076. * // => 1
  1077. */
  1078. function last(array, n, guard) {
  1079. var length = array.length;
  1080. return (n == undefined || guard) ? array[length - 1] : slice.call(array, -n || length);
  1081. }
  1082. /**
  1083. * Gets the index at which the last occurrence of `value` is found using
  1084. * strict equality for comparisons, i.e. `===`.
  1085. *
  1086. * @static
  1087. * @memberOf _
  1088. * @category Arrays
  1089. * @param {Array} array The array to search.
  1090. * @param {Mixed} value The value to search for.
  1091. * @returns {Number} Returns the index of the matched value or `-1`.
  1092. * @example
  1093. *
  1094. * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
  1095. * // => 4
  1096. */
  1097. function lastIndexOf(array, value) {
  1098. if (!array) {
  1099. return -1;
  1100. }
  1101. var index = array.length;
  1102. while (index--) {
  1103. if (array[index] === value) {
  1104. return index;
  1105. }
  1106. }
  1107. return -1;
  1108. }
  1109. /**
  1110. * Creates an array of numbers (positive and/or negative) progressing from
  1111. * `start` up to but not including `stop`. This method is a port of Python's
  1112. * `range()` function. See http://docs.python.org/library/functions.html#range.
  1113. *
  1114. * @static
  1115. * @memberOf _
  1116. * @category Arrays
  1117. * @param {Number} [start=0] The start of the range.
  1118. * @param {Number} end The end of the range.
  1119. * @param {Number} [step=1] The value to increment or descrement by.
  1120. * @returns {Array} Returns a new range array.
  1121. * @example
  1122. *
  1123. * _.range(10);
  1124. * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  1125. *
  1126. * _.range(1, 11);
  1127. * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  1128. *
  1129. * _.range(0, 30, 5);
  1130. * // => [0, 5, 10, 15, 20, 25]
  1131. *
  1132. * _.range(0, -10, -1);
  1133. * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
  1134. *
  1135. * _.range(0);
  1136. * // => []
  1137. */
  1138. function range(start, end, step) {
  1139. step || (step = 1);
  1140. if (arguments.length < 2) {
  1141. end = start || 0;
  1142. start = 0;
  1143. }
  1144. var index = -1,
  1145. length = Math.max(Math.ceil((end - start) / step), 0),
  1146. result = Array(length);
  1147. while (++index < length) {
  1148. result[index] = start;
  1149. start += step;
  1150. }
  1151. return result;
  1152. }
  1153. /**
  1154. * The opposite of `_.initial`, this method gets all but the first value of
  1155. * the `array`. Pass `n` to exclude the first `n` values from the result.
  1156. *
  1157. * @static
  1158. * @memberOf _
  1159. * @alias tail
  1160. * @category Arrays
  1161. * @param {Array} array The array to query.
  1162. * @param {Number} [n] The number of elements to return.
  1163. * @param {Object} [guard] Internally used to allow this method to work with
  1164. * others like `_.map` without using their callback `index` argument for `n`.
  1165. * @returns {Array} Returns all but the first value or `n` values of the `array`.
  1166. * @example
  1167. *
  1168. * _.rest([5, 4, 3, 2, 1]);
  1169. * // => [4, 3, 2, 1]
  1170. */
  1171. function rest(array, n, guard) {
  1172. return slice.call(array, (n == undefined || guard) ? 1 : n);
  1173. }
  1174. /**
  1175. * Produces a new array of shuffled `array` values, using a version of the
  1176. * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
  1177. *
  1178. * @static
  1179. * @memberOf _
  1180. * @category Arrays
  1181. * @param {Array} array The array to shuffle.
  1182. * @returns {Array} Returns a new shuffled array.
  1183. * @example
  1184. *
  1185. * _.shuffle([1, 2, 3, 4, 5, 6]);
  1186. * // => [4, 1, 6, 3, 5, 2]
  1187. */
  1188. function shuffle(array) {
  1189. var rand,
  1190. index = -1,
  1191. length = array.length,
  1192. result = Array(length);
  1193. while (++index < length) {
  1194. rand = Math.floor(Math.random() * (index + 1));
  1195. result[index] = result[rand];
  1196. result[rand] = array[index];
  1197. }
  1198. return result;
  1199. }
  1200. /**
  1201. * Uses a binary search to determine the smallest index at which the `value`
  1202. * should be inserted into the `collection` in order to maintain the sort order
  1203. * of the `collection`. If `callback` is passed, it will be executed for each
  1204. * value in the `collection` to compute their sort ranking. The `callback` is
  1205. * invoked with 1 argument; (value).
  1206. *
  1207. * @static
  1208. * @memberOf _
  1209. * @category Arrays
  1210. * @param {Array} array The array to iterate over.
  1211. * @param {Mixed} value The value to evaluate.
  1212. * @param {Function} [callback] The function called per iteration.
  1213. * @returns {Number} Returns the index at which the value should be inserted
  1214. * into the collection.
  1215. * @example
  1216. *
  1217. * _.sortedIndex([10, 20, 30, 40, 50], 35);
  1218. * // => 3
  1219. */
  1220. function sortedIndex(array, value, callback) {
  1221. var mid,
  1222. low = 0,
  1223. high = array.length;
  1224. if (callback) {
  1225. value = callback(value);
  1226. }
  1227. while (low < high) {
  1228. mid = (low + high) >> 1;
  1229. if ((callback ? callback(array[mid]) : array[mid]) < value) {
  1230. low = mid + 1;
  1231. } else {
  1232. high = mid;
  1233. }
  1234. }
  1235. return low;
  1236. }
  1237. /**
  1238. * Computes the union of the passed-in arrays.
  1239. *
  1240. * @static
  1241. * @memberOf _
  1242. * @category Arrays
  1243. * @param {Mixed} [array1, array2, ...] Arrays to process.
  1244. * @returns {Array} Returns a new array of unique values, in order, that are
  1245. * present in one or more of the arrays.
  1246. * @example
  1247. *
  1248. * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
  1249. * // => [1, 2, 3, 101, 10]
  1250. */
  1251. function union() {
  1252. var index = -1,
  1253. result = [],
  1254. flattened = concat.apply(result, arguments),
  1255. length = flattened.length;
  1256. while (++index < length) {
  1257. if (indexOf(result, flattened[index]) < 0) {
  1258. result.push(flattened[index]);
  1259. }
  1260. }
  1261. return result;
  1262. }
  1263. /**
  1264. * Produces a duplicate-value-free version of the `array` using strict equality
  1265. * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true`
  1266. * for `isSorted` will run a faster algorithm. If `callback` is passed,
  1267. * each value of `array` is passed through a transformation `callback` before
  1268. * uniqueness is computed. The `callback` is invoked with 3 arguments;
  1269. * (value, index, array).
  1270. *
  1271. * @static
  1272. * @memberOf _
  1273. * @alias unique
  1274. * @category Arrays
  1275. * @param {Array} array The array to process.
  1276. * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted.
  1277. * @param {Function} [callback] A
  1278. * @returns {Array} Returns a duplicate-value-free array.
  1279. * @example
  1280. *
  1281. * _.uniq([1, 2, 1, 3, 1, 4]);
  1282. * // => [1, 2, 3, 4]
  1283. */
  1284. function uniq(array, isSorted, callback) {
  1285. var computed,
  1286. index = -1,
  1287. length = array.length,
  1288. result = [],
  1289. seen = [];
  1290. if (length < 3) {
  1291. isSorted = true;
  1292. }
  1293. while (++index < length) {
  1294. computed = callback ? callback(array[index]) : array[index];
  1295. if (isSorted
  1296. ? !index || seen[seen.length - 1] !== computed
  1297. : indexOf(seen, computed) < 0
  1298. ) {
  1299. seen.push(computed);
  1300. result.push(array[index]);
  1301. }
  1302. }
  1303. return result;
  1304. }
  1305. /**
  1306. * Produces a new array with all occurrences of the values removed using strict
  1307. * equality for comparisons, i.e. `===`.
  1308. *
  1309. * @static
  1310. * @memberOf _
  1311. * @category Arrays
  1312. * @param {Array} array The array to filter.
  1313. * @param {Mixed} [value1, value2, ...] Values to remove.
  1314. * @returns {Array} Returns a new filtered array.
  1315. * @example
  1316. *
  1317. * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
  1318. * // => [2, 3, 4]
  1319. */
  1320. function without(array) {
  1321. var excluded = slice.call(arguments, 1),
  1322. index = -1,
  1323. length = array.length,
  1324. result = [];
  1325. while (++index < length) {
  1326. if (indexOf(excluded, array[index]) < 0) {
  1327. result.push(array[index]);
  1328. }
  1329. }
  1330. return result;
  1331. }
  1332. /**
  1333. * Merges together the values of each of the arrays with the value at the
  1334. * corresponding position. Useful for separate data sources that are coordinated
  1335. * through matching array indexes. For a matrix of nested arrays, `_.zip.apply(...)`
  1336. * can transpose the matrix in a similar fashion.
  1337. *
  1338. * @static
  1339. * @memberOf _
  1340. * @category Arrays
  1341. * @param {Mixed} [array1, array2, ...] Arrays to process.
  1342. * @returns {Array} Returns a new array of merged arrays.
  1343. * @example
  1344. *
  1345. * _.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
  1346. * // => [['moe', 30, true], ['larry', 40, false], ['curly', 50, false]]
  1347. */
  1348. function zip() {
  1349. var index = -1,
  1350. length = max(pluck(arguments, 'length')),
  1351. result = Array(length);
  1352. while (++index < length) {
  1353. result[index] = pluck(arguments, index);
  1354. }
  1355. return result;
  1356. }
  1357. /*--------------------------------------------------------------------------*/
  1358. /**
  1359. * Creates a new function that is restricted to executing only after it is
  1360. * called a given number of `times`.
  1361. *
  1362. * @static
  1363. * @memberOf _
  1364. * @category Functions
  1365. * @param {Number} times The number of times the function must be called before
  1366. * it is executed.
  1367. * @param {Function} func The function to restrict.
  1368. * @returns {Function} Returns the new restricted function.
  1369. * @example
  1370. *
  1371. * var renderNotes = _.after(notes.length, render);
  1372. * _.forEach(notes, function(note) {
  1373. * note.asyncSave({ 'success': renderNotes });
  1374. * });
  1375. * // renderNotes is run once, after all notes have saved.
  1376. */
  1377. function after(times, func) {
  1378. if (times < 1) {
  1379. return func();
  1380. }
  1381. return function() {
  1382. if (--times < 1) {
  1383. return func.apply(this, arguments);
  1384. }
  1385. };
  1386. }
  1387. /**
  1388. * Creates a new function that, when called, invokes `func` with the `this`
  1389. * binding of `thisArg` and prepends additional arguments to those passed to
  1390. * the bound function. Lazy defined methods may be bound by passing the object
  1391. * they are bound to as `func` and the method name as `thisArg`.
  1392. *
  1393. * @static
  1394. * @memberOf _
  1395. * @category Functions
  1396. * @param {Function|Object} func The function to bind or the object the method belongs to.
  1397. * @param @param {Mixed} [thisArg] The `this` binding of `func` or the method name.
  1398. * @param {Mixed} [arg1, arg2, ...] Arguments to prepend to those passed to the bound function.
  1399. * @returns {Function} Returns the new bound function.
  1400. * @example
  1401. *
  1402. * // basic bind
  1403. * var func = function(greeting) { return greeting + ': ' + this.name; };
  1404. * func = _.bind(func, { 'name': 'moe' }, 'hi');
  1405. * func();
  1406. * // => 'hi: moe'
  1407. *
  1408. * // lazy bind
  1409. * var object = {
  1410. * 'name': 'moe',
  1411. * 'greet': function(greeting) {
  1412. * return greeting + ': ' + this.name;
  1413. * }
  1414. * };
  1415. *
  1416. * var func = _.bind(object, 'greet', 'hi');
  1417. * func();
  1418. * // => 'hi: moe'
  1419. *
  1420. * object.greet = function(greeting) {
  1421. * return greeting + ' ' + this.name + '!';
  1422. * };
  1423. *
  1424. * func();
  1425. * // => 'hi moe!'
  1426. */
  1427. function bind(func, thisArg) {
  1428. var args = slice.call(arguments, 2),
  1429. argsLength = args.length,
  1430. isFunc = toString.call(func) == funcClass;
  1431. // juggle arguments
  1432. if (!isFunc) {
  1433. var methodName = thisArg;
  1434. thisArg = func;
  1435. }
  1436. return function() {
  1437. push.apply(args, arguments);
  1438. var result = (isFunc ? func : thisArg[methodName]).apply(thisArg, args);
  1439. args.length = argsLength;
  1440. return result;
  1441. };
  1442. }
  1443. /**
  1444. * Binds methods on the `object` to the object, overwriting the non-bound method.
  1445. * If no method names are provided, all the function properties of the `object`
  1446. * will be bound.
  1447. *
  1448. * @static
  1449. * @memberOf _
  1450. * @category Functions
  1451. * @param {Object} object The object to bind and assign the bound methods to.
  1452. * @param {Mixed} [methodName1, methodName2, ...] Method names on the object to bind.
  1453. * @returns {Object} Returns the `object`.
  1454. * @example
  1455. *
  1456. * var buttonView = {
  1457. * 'label': 'lodash',
  1458. * 'onClick': function() { alert('clicked: ' + this.label); },
  1459. * 'onHover': function() { console.log('hovering: ' + this.label); }
  1460. * };
  1461. *
  1462. * _.bindAll(buttonView);
  1463. * jQuery('#lodash_button').on('click', buttonView.onClick);
  1464. * // => When the button is clicked, `this.label` will have the correct value
  1465. */
  1466. function bindAll(object) {
  1467. var funcs = arguments,
  1468. index = 1;
  1469. if (funcs.length == 1) {
  1470. index = 0;
  1471. funcs = functions(object);
  1472. }
  1473. for (var length = funcs.length; index < length; index++) {
  1474. object[funcs[index]] = bind(object[funcs[index]], object);
  1475. }
  1476. return object;
  1477. }
  1478. /**
  1479. * Creates a new function that is the composition of the passed functions,
  1480. * where each function consumes the return value of the function that follows.
  1481. * In math terms, composing thefunctions `f()`, `g()`, and `h()` produces `f(g(h()))`.
  1482. *
  1483. * @static
  1484. * @memberOf _
  1485. * @category Functions
  1486. * @param {Mixed} [func1, func2, ...] Functions to compose.
  1487. * @returns {Function} Returns the new composed function.
  1488. * @example
  1489. *
  1490. * var greet = function(name) { return 'hi: ' + name; };
  1491. * var exclaim = function(statement) { return statement + '!'; };
  1492. * var welcome = _.compose(exclaim, greet);
  1493. * welcome('moe');
  1494. * // => 'hi: moe!'
  1495. */
  1496. function compose() {
  1497. var funcs = arguments;
  1498. return function() {
  1499. var args = arguments,
  1500. length = funcs.length;
  1501. while (length--) {
  1502. args = [funcs[length].apply(this, args)];
  1503. }
  1504. return args[0];
  1505. };
  1506. }
  1507. /**
  1508. * Creates a new function that will delay the execution of `func` until after
  1509. * `wait` milliseconds have elapsed since the last time it was invoked. Pass
  1510. * `true` for `immediate` to cause debounce to invoke `func` on the leading,
  1511. * instead of the trailing, edge of the `wait` timeout.
  1512. *
  1513. * @static
  1514. * @memberOf _
  1515. * @category Functions
  1516. * @param {Function} func The function to debounce.
  1517. * @param {Number} wait The number of milliseconds to delay.
  1518. * @param {Boolean} immediate A flag to indicate execution is on the leading
  1519. * edge of the timeout.
  1520. * @returns {Function} Returns the new debounced function.
  1521. * @example
  1522. *
  1523. * var lazyLayout = _.debounce(calculateLayout, 300);
  1524. * jQuery(window).on('resize', lazyLayout);
  1525. */
  1526. function debounce(func, wait, immediate) {
  1527. var args,
  1528. result,
  1529. thisArg,
  1530. timeoutId;
  1531. function delayed() {
  1532. timeoutId = undefined;
  1533. if (!immediate) {
  1534. func.apply(thisArg, args);
  1535. }
  1536. }
  1537. return function() {
  1538. var isImmediate = immediate && !timeoutId;
  1539. args = arguments;
  1540. thisArg = this;
  1541. clearTimeout(timeoutId);
  1542. timeoutId = setTimeout(delayed, wait);
  1543. if (isImmediate) {
  1544. result = func.apply(thisArg, args);
  1545. }
  1546. return result;
  1547. };
  1548. }
  1549. /**
  1550. * Executes the `func` function after `wait` milliseconds. Additional arguments
  1551. * are passed to `func` when it is invoked.
  1552. *
  1553. * @static
  1554. * @memberOf _
  1555. * @category Functions
  1556. * @param {Function} func The function to delay.
  1557. * @param {Number} wait The number of milliseconds to delay execution.
  1558. * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
  1559. * @returns {Number} Returns the `setTimeout` timeout id.
  1560. * @example
  1561. *
  1562. * var log = _.bind(console.log, console);
  1563. * _.delay(log, 1000, 'logged later');
  1564. * // => 'logged later' (Appears after one second.)
  1565. */
  1566. function delay(func, wait) {
  1567. var args = slice.call(arguments, 2);
  1568. return setTimeout(function() { return func.apply(undefined, args); }, wait);
  1569. }
  1570. /**
  1571. * Defers executing the `func` function until the current call stack has cleared.
  1572. * Additional arguments are passed to `func` when it is invoked.
  1573. *
  1574. * @static
  1575. * @memberOf _
  1576. * @category Functions
  1577. * @param {Function} func The function to defer.
  1578. * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with.
  1579. * @returns {Number} Returns the `setTimeout` timeout id.
  1580. * @example
  1581. *
  1582. * _.defer(function() { alert('deferred'); });
  1583. * // Returns from the function before the alert runs.
  1584. */
  1585. function defer(func) {
  1586. var args = slice.call(arguments, 1);
  1587. return setTimeout(function() { return func.apply(undefined, args); }, 1);
  1588. }
  1589. /**
  1590. * Creates a new function that memoizes the result of `func`. If `resolver` is
  1591. * passed, it will be used to determine the cache key for storing the result
  1592. * based on the arguments passed to the memoized function. By default, the first
  1593. * argument passed to the memoized function is used as the cache key.
  1594. *
  1595. * @static
  1596. * @memberOf _
  1597. * @category Functions
  1598. * @param {Function} func The function to have its output memoized.
  1599. * @param {Function} [resolver] A function used to resolve the cache key.
  1600. * @returns {Function} Returns the new memoizing function.
  1601. * @example
  1602. *
  1603. * var fibonacci = _.memoize(function(n) {
  1604. * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
  1605. * });
  1606. */
  1607. function memoize(func, resolver) {
  1608. var cache = {};
  1609. return function() {
  1610. var prop = resolver ? resolver.apply(this, arguments) : arguments[0];
  1611. return hasOwnProperty.call(cache, prop)
  1612. ? cache[prop]
  1613. : (cache[prop] = func.apply(this, arguments));
  1614. };
  1615. }
  1616. /**
  1617. * Creates a new function that is restricted to one execution. Repeat calls to
  1618. * the function will return the value of the first call.
  1619. *
  1620. * @static
  1621. * @memberOf _
  1622. * @category Functions
  1623. * @param {Function} func The function to restrict.
  1624. * @returns {Function} Returns the new restricted function.
  1625. * @example
  1626. *
  1627. * var initialize = _.once(createApplication);
  1628. * initialize();
  1629. * initialize();
  1630. * // Application is only created once.
  1631. */
  1632. function once(func) {
  1633. var result,
  1634. ran = false;
  1635. return function() {
  1636. if (ran) {
  1637. return result;
  1638. }
  1639. ran = true;
  1640. result = func.apply(this, arguments);
  1641. return result;
  1642. };
  1643. }
  1644. /**
  1645. * Creates a new function that, when executed, will only call the `func`
  1646. * function at most once per every `wait` milliseconds. If the throttled function
  1647. * is invoked more than once, `func` will also be called on the trailing edge
  1648. * of the `wait` timeout.
  1649. *
  1650. * @static
  1651. * @memberOf _
  1652. * @category Functions
  1653. * @param {Function} func The function to throttle.
  1654. * @param {Number} wait The number of milliseconds to throttle executions to.
  1655. * @returns {Function} Returns the new throttled function.
  1656. * @example
  1657. *
  1658. * var throttled = _.throttle(updatePosition, 100);
  1659. * jQuery(window).on('scroll', throttled);
  1660. */
  1661. function throttle(func, wait) {
  1662. var args,
  1663. result,
  1664. thisArg,
  1665. timeoutId,
  1666. lastCalled = 0;
  1667. function trailingCall() {
  1668. lastCalled = new Date;
  1669. timeoutId = undefined;
  1670. func.apply(thisArg, args);
  1671. }
  1672. return function() {
  1673. var now = new Date,
  1674. remain = wait - (now - lastCalled);
  1675. args = arguments;
  1676. thisArg = this;
  1677. if (remain <= 0) {
  1678. lastCalled = now;
  1679. result = func.apply(thisArg, args);
  1680. }
  1681. else if (!timeoutId) {
  1682. timeoutId = setTimeout(trailingCall, remain);
  1683. }
  1684. return result;
  1685. };
  1686. }
  1687. /**
  1688. * Create a new function that passes the `func` function to the `wrapper`
  1689. * function as its first argument. Additional arguments are appended to those
  1690. * passed to the `wrapper` function.
  1691. *
  1692. * @static
  1693. * @memberOf _
  1694. * @category Functions
  1695. * @param {Function} func The function to wrap.
  1696. * @param {Function} wrapper The wrapper function.
  1697. * @param {Mixed} [arg1, arg2, ...] Arguments to append to those passed to the wrapper.
  1698. * @returns {Function} Returns the new function.
  1699. * @example
  1700. *
  1701. * var hello = function(name) { return 'hello: ' + name; };
  1702. * hello = _.wrap(hello, function(func) {
  1703. * return 'before, ' + func('moe') + ', after';
  1704. * });
  1705. * hello();
  1706. * // => 'before, hello: moe, after'
  1707. */
  1708. function wrap(func, wrapper) {
  1709. return function() {
  1710. var args = [func];
  1711. push.apply(args, arguments);
  1712. return wrapper.apply(this, args);
  1713. };
  1714. }
  1715. /*--------------------------------------------------------------------------*/
  1716. /**
  1717. * Create a shallow clone of the `value`. Any nested objects or arrays will be
  1718. * assigned by reference and not cloned.
  1719. *
  1720. * @static
  1721. * @memberOf _
  1722. * @category Objects
  1723. * @param {Mixed} value The value to clone.
  1724. * @returns {Mixed} Returns the cloned `value`.
  1725. * @example
  1726. *
  1727. * _.clone({ 'name': 'moe' });
  1728. * // => { 'name': 'moe' };
  1729. */
  1730. function clone(value) {
  1731. if (value !== Object(value)) {
  1732. return value;
  1733. }
  1734. return isArray(value) ? value.slice() : extend({}, value);
  1735. }
  1736. /**
  1737. * Assigns missing properties in `object` with default values from the defaults
  1738. * objects. As soon as a property is set, additional defaults of the same
  1739. * property will be ignored.
  1740. *
  1741. * @static
  1742. * @memberOf _
  1743. * @category Objects
  1744. * @param {Object} object The object to populate.
  1745. * @param {Object} [defaults1, defaults2, ..] The defaults objects to apply to `object`.
  1746. * @returns {Object} Returns `object`.
  1747. * @example
  1748. *
  1749. * var iceCream = { 'flavor': 'chocolate' };
  1750. * _.defaults(iceCream, { 'flavor': 'vanilla', 'sprinkles': 'lots' });
  1751. * // => { 'flavor': 'chocolate', 'sprinkles': 'lots' }
  1752. */
  1753. var defaults = iterationFactory(extendFactoryOptions, {
  1754. 'inLoop': 'if (object[index] == undefined)' + extendFactoryOptions.inLoop
  1755. });
  1756. /**
  1757. * Copies enumerable properties from the source objects to the `destination` object.
  1758. * Subsequent sources will overwrite propery assignments of previous sources.
  1759. *
  1760. * @static
  1761. * @memberOf _
  1762. * @category Objects
  1763. * @param {Object} object The destination object.
  1764. * @param {Object} [source1, source2, ..] The source objects.
  1765. * @returns {Object} Returns the destination object.
  1766. * @example
  1767. *
  1768. * _.extend({ 'name': 'moe' }, { 'age': 40 });
  1769. * // => { 'name': 'moe', 'age': 40 }
  1770. */
  1771. var extend = iterationFactory(extendFactoryOptions);
  1772. /**
  1773. * Produces a sorted array of the properties, own and inherited, of `object`
  1774. * that have function values.
  1775. *
  1776. * @static
  1777. * @memberOf _
  1778. * @alias methods
  1779. * @category Objects
  1780. * @param {Object} object The object to inspect.
  1781. * @returns {Array} Returns a new array of property names that have function values.
  1782. * @example
  1783. *
  1784. * _.functions(_);
  1785. * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
  1786. */
  1787. var functions = iterationFactory({
  1788. 'args': 'object',
  1789. 'init': '[]',
  1790. 'useHas': false,
  1791. 'inLoop': 'if (toString.call(object[index]) == funcClass) result.push(index)',
  1792. 'bottom': 'result.sort()'
  1793. });
  1794. /**
  1795. * Checks if the specified object `property` exists and is a direct property,
  1796. * instead of an inherited property.
  1797. *
  1798. * @static
  1799. * @memberOf _
  1800. * @category Objects
  1801. * @param {Object} object The object to check.
  1802. * @param {String} property The property to check for.
  1803. * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
  1804. * @example
  1805. *
  1806. * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
  1807. * // => true
  1808. */
  1809. function has(object, property) {
  1810. return hasOwnProperty.call(object, property);
  1811. }
  1812. /**
  1813. * Checks if a `value` is an `arguments` object.
  1814. *
  1815. * @static
  1816. * @memberOf _
  1817. * @category Objects
  1818. * @param {Mixed} value The value to check.
  1819. * @returns {Boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
  1820. * @example
  1821. *
  1822. * (function() { return _.isArguments(arguments); })(1, 2, 3);
  1823. * // => true
  1824. *
  1825. * _.isArguments([1, 2, 3]);
  1826. * // => false
  1827. */
  1828. var isArguments = function isArguments(value) {
  1829. return toString.call(value) == '[object Arguments]';
  1830. };
  1831. // fallback for browser like IE<9 which detect `arguments` as `[object Object]`
  1832. if (!isArguments(arguments)) {
  1833. isArguments = function(value) {
  1834. return !!(value && hasOwnProperty.call(value, 'callee'));
  1835. };
  1836. }
  1837. /**
  1838. * Checks if a `value` is a boolean (`true` or `false`) value.
  1839. *
  1840. * @static
  1841. * @memberOf _
  1842. * @category Objects
  1843. * @param {Mixed} value The value to check.
  1844. * @returns {Boolean} Returns `true` if the `value` is a boolean value, else `false`.
  1845. * @example
  1846. *
  1847. * _.isBoolean(null);
  1848. * // => false
  1849. */
  1850. function isBoolean(value) {
  1851. return value === true || value === false || toString.call(value) == boolClass;
  1852. }
  1853. /**
  1854. * Checks if a `value` is a date.
  1855. *
  1856. * @static
  1857. * @memberOf _
  1858. * @category Objects
  1859. * @param {Mixed} value The value to check.
  1860. * @returns {Boolean} Returns `true` if the `value` is a date, else `false`.
  1861. * @example
  1862. *
  1863. * _.isDate(new Date);
  1864. * // => true
  1865. */
  1866. function isDate(value) {
  1867. return toString.call(value) == dateClass;
  1868. }
  1869. /**
  1870. * Checks if a `value` is a DOM element.
  1871. *
  1872. * @static
  1873. * @memberOf _
  1874. * @category Objects
  1875. * @param {Mixed} value The value to check.
  1876. * @returns {Boolean} Returns `true` if the `value` is a DOM element, else `false`.
  1877. * @example
  1878. *
  1879. * _.isElement(document.body);
  1880. * // => true
  1881. */
  1882. function isElement(value) {
  1883. return !!(value && value.nodeType == 1);
  1884. }
  1885. /**
  1886. * Performs a deep comparison between two values to determine if they are
  1887. * equivalent to each other.
  1888. *
  1889. * @static
  1890. * @memberOf _
  1891. * @category Objects
  1892. * @param {Mixed} a The value to compare.
  1893. * @param {Mixed} b The other value to compare.
  1894. * @param {Array} [stack] Internally used to keep track of "seen" objects to
  1895. * avoid circular references.
  1896. * @returns {Boolean} Returns `true` if the values are equvalent, else `false`.
  1897. * @example
  1898. *
  1899. * var moe = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
  1900. * var clone = { 'name': 'moe', 'luckyNumbers': [13, 27, 34] };
  1901. *
  1902. * moe == clone;
  1903. * // => false
  1904. *
  1905. * _.isEqual(moe, clone);
  1906. * // => true
  1907. */
  1908. function isEqual(a, b, stack) {
  1909. stack || (stack = []);
  1910. // exit early for identical values
  1911. if (a === b) {
  1912. // treat `+0` vs. `-0` as not equal
  1913. return a !== 0 || (1 / a == 1 / b);
  1914. }
  1915. // a strict comparison is necessary because `null == undefined`
  1916. if (a == undefined || b == undefined) {
  1917. return a === b;
  1918. }
  1919. // unwrap any wrapped objects
  1920. if (a._chain) {
  1921. a = a._wrapped;
  1922. }
  1923. if (b._chain) {
  1924. b = b._wrapped;
  1925. }
  1926. // invoke a custom `isEqual` method if one is provided
  1927. if (a.isEqual && toString.call(a.isEqual) == funcClass) {
  1928. return a.isEqual(b);
  1929. }
  1930. if (b.isEqual && toString.call(b.isEqual) == funcClass) {
  1931. return b.isEqual(a);
  1932. }
  1933. // compare [[Class]] names
  1934. var className = toString.call(a);
  1935. if (className != toString.call(b)) {
  1936. return false;
  1937. }
  1938. switch (className) {
  1939. // strings, numbers, dates, and booleans are compared by value
  1940. case stringClass:
  1941. // primitives and their corresponding object instances are equivalent;
  1942. // thus, `'5'` is quivalent to `new String('5')`
  1943. return a == String(b);
  1944. case numberClass:
  1945. // treat `NaN` vs. `NaN` as equal
  1946. return a != +a
  1947. ? b != +b
  1948. // but treat `+0` vs. `-0` as not equal
  1949. : (a == 0 ? (1 / a == 1 / b) : a == +b);
  1950. case boolClass:
  1951. case dateClass:
  1952. // coerce dates and booleans to numeric values, dates to milliseconds and booleans to 1 or 0;
  1953. // treat invalid dates coerced to `NaN` as not equal
  1954. return +a == +b;
  1955. // regexps are compared by their source and flags
  1956. case regexpClass:
  1957. return a.source == b.source &&
  1958. a.global == b.global &&
  1959. a.multiline == b.multiline &&
  1960. a.ignoreCase == b.ignoreCase;
  1961. }
  1962. if (typeof a != 'object' || typeof b != 'object') {
  1963. return false;
  1964. }
  1965. // Assume equality for cyclic structures. The algorithm for detecting cyclic
  1966. // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  1967. var length = stack.length;
  1968. while (length--) {
  1969. // Linear search. Performance is inversely proportional to the number of
  1970. // unique nested structures.
  1971. if (stack[length] == a) {
  1972. return true;
  1973. }
  1974. }
  1975. var result = true,
  1976. size = 0;
  1977. // add the first collection to the stack of traversed objects
  1978. stack.push(a);
  1979. // recursively compare objects and arrays
  1980. if (className == arrayClass) {
  1981. // compare array lengths to determine if a deep comparison is necessary
  1982. size = a.length;
  1983. result = size == b.length;
  1984. if (result) {
  1985. // deep compare the contents, ignoring non-numeric properties
  1986. while (size--) {
  1987. // ensure commutative equality for sparse arrays
  1988. if (!(result = size in a == size in b && isEqual(a[size], b[size], stack))) {
  1989. break;
  1990. }
  1991. }
  1992. }
  1993. } else {
  1994. // objects with different constructors are not equivalent
  1995. if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
  1996. return false;
  1997. }
  1998. // deep compare objects
  1999. for (var prop in a) {
  2000. if (hasOwnProperty.call(a, prop)) {
  2001. // count the expected number of properties
  2002. size++;
  2003. // deep compare each member
  2004. if (!(result = hasOwnProperty.call(b, prop) && isEqual(a[prop], b[prop], stack))) {
  2005. break;
  2006. }
  2007. }
  2008. }
  2009. // ensure that both objects contain the same number of properties
  2010. if (result) {
  2011. for (prop in b) {
  2012. if (hasOwnProperty.call(b, prop) && !(size--)) {
  2013. break;
  2014. }
  2015. }
  2016. result = !size;
  2017. }
  2018. }
  2019. // remove the first collection from the stack of traversed objects
  2020. stack.pop();
  2021. return result;
  2022. }
  2023. /**
  2024. * Checks if a `value` is a finite number.
  2025. *
  2026. * @static
  2027. * @memberOf _
  2028. * @category Objects
  2029. * @param {Mixed} value The value to check.
  2030. * @returns {Boolean} Returns `true` if the `value` is a finite number, else `false`.
  2031. * @example
  2032. *
  2033. * _.isFinite(-101);
  2034. * // => true
  2035. *
  2036. * _.isFinite('10');
  2037. * // => false
  2038. *
  2039. * _.isFinite(Infinity);
  2040. * // => false
  2041. */
  2042. function isFinite(value) {
  2043. return nativeIsFinite(value) && toString.call(value) == numberClass;
  2044. }
  2045. /**
  2046. * Checks if a `value` is a function.
  2047. *
  2048. * @static
  2049. * @memberOf _
  2050. * @category Objects
  2051. * @param {Mixed} value The value to check.
  2052. * @returns {Boolean} Returns `true` if the `value` is a function, else `false`.
  2053. * @example
  2054. *
  2055. * _.isFunction(''.concat);
  2056. * // => true
  2057. */
  2058. function isFunction(value) {
  2059. return toString.call(value) == funcClass;
  2060. }
  2061. /**
  2062. * Checks if a `value` is an object.
  2063. *
  2064. * @static
  2065. * @memberOf _
  2066. * @category Objects
  2067. * @param {Mixed} value The value to check.
  2068. * @returns {Boolean} Returns `true` if the `value` is an object, else `false`.
  2069. * @example
  2070. *
  2071. * _.isObject({});
  2072. * // => true
  2073. *
  2074. * _.isObject(1);
  2075. * // => false
  2076. */
  2077. function isObject(value) {
  2078. return value === Object(value);
  2079. }
  2080. /**
  2081. * Checks if a `value` is `NaN`.
  2082. * Note: this is not the same as native `isNaN`, which will return true for
  2083. * `undefined` and other values. See http://es5.github.com/#x15.1.2.4.
  2084. *
  2085. * @static
  2086. * @memberOf _
  2087. * @category Objects
  2088. * @param {Mixed} value The value to check.
  2089. * @returns {Boolean} Returns `true` if the `value` is `NaN`, else `false`.
  2090. * @example
  2091. *
  2092. * _.isNaN(NaN);
  2093. * // => true
  2094. *
  2095. * _.isNaN(new Number(NaN));
  2096. * // => true
  2097. *
  2098. * isNaN(undefined);
  2099. * // => true
  2100. *
  2101. * _.isNaN(undefined);
  2102. * // => false
  2103. */
  2104. function isNaN(value) {
  2105. // `NaN` as a primitive is the only value that is not equal to itself
  2106. // (perform the [[Class]] check first to avoid errors with some host objects in IE)
  2107. return toString.call(value) == numberClass && value != +value
  2108. }
  2109. /**
  2110. * Checks if a `value` is `null`.
  2111. *
  2112. * @static
  2113. * @memberOf _
  2114. * @category Objects
  2115. * @param {Mixed} value The value to check.
  2116. * @returns {Boolean} Returns `true` if the `value` is `null`, else `false`.
  2117. * @example
  2118. *
  2119. * _.isNull(null);
  2120. * // => true
  2121. *
  2122. * _.isNull(undefined);
  2123. * // => false
  2124. */
  2125. function isNull(value) {
  2126. return value === null;
  2127. }
  2128. /**
  2129. * Checks if a `value` is a number.
  2130. *
  2131. * @static
  2132. * @memberOf _
  2133. * @category Objects
  2134. * @param {Mixed} value The value to check.
  2135. * @returns {Boolean} Returns `true` if the `value` is a number, else `false`.
  2136. * @example
  2137. *
  2138. * _.isNumber(8.4 * 5;
  2139. * // => true
  2140. */
  2141. function isNumber(value) {
  2142. return toString.call(value) == numberClass;
  2143. }
  2144. /**
  2145. * Checks if a `value` is a regular expression.
  2146. *
  2147. * @static
  2148. * @memberOf _
  2149. * @category Objects
  2150. * @param {Mixed} value The value to check.
  2151. * @returns {Boolean} Returns `true` if the `value` is a regular expression, else `false`.
  2152. * @example
  2153. *
  2154. * _.isRegExp(/moe/);
  2155. * // => true
  2156. */
  2157. function isRegExp(value) {
  2158. return toString.call(value) == regexpClass;
  2159. }
  2160. /**
  2161. * Checks if a `value` is a string.
  2162. *
  2163. * @static
  2164. * @memberOf _
  2165. * @category Objects
  2166. * @param {Mixed} value The value to check.
  2167. * @returns {Boolean} Returns `true` if the `value` is a string, else `false`.
  2168. * @example
  2169. *
  2170. * _.isString('moe');
  2171. * // => true
  2172. */
  2173. function isString(value) {
  2174. return toString.call(value) == stringClass;
  2175. }
  2176. /**
  2177. * Checks if a `value` is `undefined`.
  2178. *
  2179. * @static
  2180. * @memberOf _
  2181. * @category Objects
  2182. * @param {Mixed} value The value to check.
  2183. * @returns {Boolean} Returns `true` if the `value` is `undefined`, else `false`.
  2184. * @example
  2185. *
  2186. * _.isUndefined(void 0);
  2187. * // => true
  2188. */
  2189. function isUndefined(value) {
  2190. return value === undefined;
  2191. }
  2192. /**
  2193. * Produces an array of the `object`'s enumerable own property names.
  2194. *
  2195. * @static
  2196. * @memberOf _
  2197. * @category Objects
  2198. * @param {Object} object The object to inspect.
  2199. * @returns {Array} Returns a new array of property names.
  2200. * @example
  2201. *
  2202. * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
  2203. * // => ['one', 'two', 'three']
  2204. */
  2205. var keys = nativeKeys || iterationFactory({
  2206. 'args': 'object',
  2207. 'exit': 'if (object !== Object(object)) throw TypeError()',
  2208. 'init': '[]',
  2209. 'inLoop': 'result.push(index)'
  2210. });
  2211. /**
  2212. * Creates an object composed of the specified properties. Property names may
  2213. * be specified as individual arguments or as arrays of property names.
  2214. *
  2215. * @static
  2216. * @memberOf _
  2217. * @category Objects
  2218. * @param {Object} object The object to pluck.
  2219. * @param {Object} [prop1, prop2, ..] The properties to pick.
  2220. * @returns {Object} Returns an object composed of the picked properties.
  2221. * @example
  2222. *
  2223. * _.pick({ 'name': 'moe', 'age': 40, 'userid': 'moe1' }, 'name', 'age');
  2224. * // => { 'name': 'moe', 'age': 40 }
  2225. */
  2226. function pick(object) {
  2227. var prop,
  2228. index = 0,
  2229. props = concat.apply(ArrayProto, arguments),
  2230. length = props.length,
  2231. result = {};
  2232. // start `index` at `1` to skip `object`
  2233. while (++index < length) {
  2234. prop = props[index];
  2235. if (prop in object) {
  2236. result[prop] = object[prop];
  2237. }
  2238. }
  2239. return result;
  2240. }
  2241. /**
  2242. * Invokes `interceptor` with the `value` as the first argument, and then returns
  2243. * `value`. The primary purpose of this method is to "tap into" a method chain,
  2244. * in order to performoperations on intermediate results within the chain.
  2245. *
  2246. * @static
  2247. * @memberOf _
  2248. * @category Objects
  2249. * @param {Mixed} value The value to pass to `callback`.
  2250. * @param {Function} interceptor The function to invoke.
  2251. * @returns {Mixed} Returns `value`.
  2252. * @example
  2253. *
  2254. * _.chain([1,2,3,200])
  2255. * .filter(function(num) { return num % 2 == 0; })
  2256. * .tap(alert)
  2257. * .map(function(num) { return num * num })
  2258. * .value();
  2259. * // => // [2, 200] (alerted)
  2260. * // => [4, 40000]
  2261. */
  2262. function tap(value, interceptor) {
  2263. interceptor(value);
  2264. return value;
  2265. }
  2266. /*--------------------------------------------------------------------------*/
  2267. /**
  2268. * Escapes a string for insertion into HTML, replacing `&`, `<`, `"`, `'`,
  2269. * and `/` characters.
  2270. *
  2271. * @static
  2272. * @memberOf _
  2273. * @category Utilities
  2274. * @param {String} string The string to escape.
  2275. * @returns {String} Returns the escaped string.
  2276. * @example
  2277. *
  2278. * _.escape('Curly, Larry & Moe');
  2279. * // => "Curly, Larry &amp; Moe"
  2280. */
  2281. function escape(string) {
  2282. return (string + '')
  2283. .replace(/&/g, '&amp;')
  2284. .replace(/</g, '&lt;')
  2285. .replace(/"/g, '&quot;')
  2286. .replace(/'/g, '&#x27;')
  2287. .replace(/\//g,'&#x2F;');
  2288. }
  2289. /**
  2290. * This function simply returns the first argument passed to it.
  2291. * Note: It is used throughout Lo-Dash as a default callback.
  2292. *
  2293. * @static
  2294. * @memberOf _
  2295. * @category Utilities
  2296. * @param {Mixed} value Any value.
  2297. * @returns {Mixed} Returns `value`.
  2298. * @example
  2299. *
  2300. * var moe = { 'name': 'moe' };
  2301. * moe === _.identity(moe);
  2302. * // => true
  2303. */
  2304. function identity(value) {
  2305. return value;
  2306. }
  2307. /**
  2308. * Adds functions properties of `object` to the `lodash` function and chainable
  2309. * wrapper.
  2310. *
  2311. * @static
  2312. * @memberOf _
  2313. * @category Utilities
  2314. * @param {Object} object The object of function properties to add to `lodash`.
  2315. * @example
  2316. *
  2317. * _.mixin({
  2318. * 'capitalize': function(string) {
  2319. * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
  2320. * }
  2321. * });
  2322. *
  2323. * _.capitalize('curly');
  2324. * // => 'Curly'
  2325. *
  2326. * _('larry').capitalize();
  2327. * // => 'Larry'
  2328. */
  2329. function mixin(object) {
  2330. forEach(functions(object), function(methodName) {
  2331. var func = lodash[methodName] = object[methodName];
  2332. lodash.prototype[methodName] = function() {
  2333. var args = [this._wrapped];
  2334. push.apply(args, arguments);
  2335. var result = func.apply(lodash, args);
  2336. return this._chain ? new Lodash(result).chain() : result;
  2337. };
  2338. });
  2339. }
  2340. /**
  2341. * Reverts the '_' variable to its previous value and returns a reference to
  2342. * the `lodash` function.
  2343. *
  2344. * @static
  2345. * @memberOf _
  2346. * @category Utilities
  2347. * @returns {Function} Returns the `lodash` function.
  2348. * @example
  2349. *
  2350. * var lodash = _.noConflict();
  2351. */
  2352. function noConflict() {
  2353. window._ = oldDash;
  2354. return this;
  2355. }
  2356. /**
  2357. * Resolves the value of `property` on `object`. If the property is a function
  2358. * it will be invoked and its result returned, else the property value is returned.
  2359. *
  2360. * @static
  2361. * @memberOf _
  2362. * @category Utilities
  2363. * @param {Object} object The object to inspect.
  2364. * @param {String} property The property to get the result of.
  2365. * @returns {Mixed} Returns the resolved.
  2366. * @example
  2367. *
  2368. * var object = {
  2369. * 'cheese': 'crumpets',
  2370. * 'stuff': function() {
  2371. * return 'nonsense';
  2372. * }
  2373. * };
  2374. *
  2375. * _.result(object, 'cheese');
  2376. * // => 'crumpets'
  2377. *
  2378. * _.result(object, 'stuff');
  2379. * // => 'nonsense'
  2380. */
  2381. function result(object, property) {
  2382. if (!object) {
  2383. return null;
  2384. }
  2385. var value = object[property];
  2386. return toString.call(value) == funcClass ? object[property]() : value;
  2387. }
  2388. /**
  2389. * A JavaScript micro-templating method, similar to John Resig's implementation.
  2390. * Lo-Dash templating handles arbitrary delimiters, preserves whitespace, and
  2391. * correctly escapes quotes within interpolated code.
  2392. *
  2393. * @static
  2394. * @memberOf _
  2395. * @category Utilities
  2396. * @param {String} text The template text.
  2397. * @param {Obect} data The data object used to populate the text.
  2398. * @param {Object} options The options object.
  2399. * @returns {Function|String} Returns a compiled function when no `data` object
  2400. * is given, else it returns the interpolated text.
  2401. * @example
  2402. *
  2403. * // using compiled template
  2404. * var compiled = _.template('hello: <%= name %>');
  2405. * compiled({ 'name': 'moe' });
  2406. * // => 'hello: moe'
  2407. *
  2408. * var list = '% _.forEach(people, function(name) { %> <li><%= name %></li> <% }); %>';
  2409. * _.template(list, { 'people': ['moe', 'curly', 'larry'] });
  2410. * // => '<li>moe</li><li>curly</li><li>larry</li>'
  2411. *
  2412. * var template = _.template('<b><%- value %></b>');
  2413. * template({ 'value': '<script>' });
  2414. * // => '<b>&lt;script&gt;</b>'
  2415. *
  2416. * // using `print`
  2417. * var compiled = _.template('<% print("Hello " + epithet); %>');
  2418. * compiled({ 'epithet': 'stooge' });
  2419. * // => 'Hello stooge.'
  2420. *
  2421. * // using custom template settings
  2422. * _.templateSettings = {
  2423. * 'interpolate': /\{\{(.+?)\}\}/g
  2424. * };
  2425. *
  2426. * var template = _.template('Hello {{ name }}!');
  2427. * template({ 'name': 'Mustache' });
  2428. * // => 'Hello Mustache!'
  2429. *
  2430. *
  2431. * // using the `variable` option
  2432. * _.template('<%= data.hasWith %>', { 'hasWith': 'no' }, { 'variable': 'data' });
  2433. * // => 'no'
  2434. *
  2435. * // using the `source` property
  2436. * <script>
  2437. * JST.project = <%= _.template(jstText).source %>;
  2438. * </script>
  2439. */
  2440. function template(text, data, options) {
  2441. options = defaults(options || {}, lodash.templateSettings);
  2442. var result,
  2443. reEscapeDelimiter = options.escape,
  2444. reEvaluateDelimiter = options.evaluate,
  2445. reInterpolateDelimiter = options.interpolate,
  2446. variable = options.variable;
  2447. // tokenize delimiters to avoid escaping them
  2448. if (reEscapeDelimiter) {
  2449. text = text.replace(reEscapeDelimiter, tokenizeEscape);
  2450. }
  2451. if (reInterpolateDelimiter) {
  2452. text = text.replace(reInterpolateDelimiter, tokenizeInterpolate);
  2453. }
  2454. if (reEvaluateDelimiter) {
  2455. text = text.replace(reEvaluateDelimiter, tokenizeEvaluate);
  2456. }
  2457. // escape characters that cannot be included in string literals and
  2458. // detokenize delimiter code snippets
  2459. text = "__p='" + text.replace(reUnescaped, escapeChar).replace(reToken, detokenize) + "';\n";
  2460. // clear stored code snippets
  2461. tokenized.length = 0;
  2462. // if `options.variable` is not specified, add `data` to the top of the scope chain
  2463. if (!variable) {
  2464. text = 'with (object || {}) {\n' + text + '\n}\n';
  2465. }
  2466. text = 'function(' + (variable || 'object') + ') {\n' +
  2467. 'var __p, __t;\n' +
  2468. 'function print() { __p += __j.call(arguments, "") }\n' +
  2469. text +
  2470. 'return __p\n}';
  2471. result = Function('_, __e, __j', 'return ' + text)(lodash, escape, join);
  2472. if (data) {
  2473. return result(data);
  2474. }
  2475. // provide the compiled function's source via its `toString()` method, in
  2476. // supported environments, or the `source` property as a convenience for
  2477. // build time precompilation
  2478. result.source = text;
  2479. return result;
  2480. }
  2481. /**
  2482. * Executes the `callback` function `n` times. The `callback` is invoked with
  2483. * 1 argument; (index).
  2484. *
  2485. * @static
  2486. * @memberOf _
  2487. * @category Utilities
  2488. * @param {Number} n The number of times to execute the callback.
  2489. * @param {Function} callback The function called per iteration.
  2490. * @param {Mixed} [thisArg] The `this` binding for the callback.
  2491. * @example
  2492. *
  2493. * _.times(3, function() { genie.grantWish(); });
  2494. */
  2495. function times(n, callback, thisArg) {
  2496. if (thisArg) {
  2497. callback = bind(callback, thisArg);
  2498. }
  2499. for (var index = 0; index < n; index++) {
  2500. callback(index);
  2501. }
  2502. }
  2503. /**
  2504. * Generates a unique id. If `prefix` is passed, the id will be appended to it.
  2505. *
  2506. * @static
  2507. * @memberOf _
  2508. * @category Utilities
  2509. * @param {String} [prefix] The value to prefix the id with.
  2510. * @returns {Number|String} Returns a numeric id if no prefix is passed, else
  2511. * a string id may be returned.
  2512. * @example
  2513. *
  2514. * _.uniqueId('contact_');
  2515. * // => 'contact_104'
  2516. */
  2517. function uniqueId(prefix) {
  2518. var id = idCounter++;
  2519. return prefix ? prefix + id : id;
  2520. }
  2521. /*--------------------------------------------------------------------------*/
  2522. /**
  2523. * Wraps the value in a `lodash` chainable object.
  2524. *
  2525. * @static
  2526. * @memberOf _
  2527. * @category Chaining
  2528. * @param {Mixed} value The value to wrap.
  2529. * @returns {Object} Returns the `lodash` chainable object.
  2530. * @example
  2531. *
  2532. * var stooges = [
  2533. * { 'name': 'moe', 'age': 40 },
  2534. * { 'name': 'larry', 'age': 50 },
  2535. * { 'name': 'curly', 'age': 60 }
  2536. * ];
  2537. *
  2538. * var youngest = _.chain(stooges)
  2539. * .sortBy(function(stooge) { return stooge.age; })
  2540. * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })
  2541. * .first()
  2542. * .value();
  2543. * // => 'moe is 40'
  2544. */
  2545. function chain(value) {
  2546. return new Lodash(value).chain();
  2547. }
  2548. /**
  2549. * Extracts the value from a wrapped chainable object.
  2550. *
  2551. * @name chain
  2552. * @memberOf _
  2553. * @category Chaining
  2554. * @returns {Mixed} Returns the wrapped object.
  2555. * @example
  2556. *
  2557. * _([1, 2, 3]).value();
  2558. * // => [1, 2, 3]
  2559. */
  2560. function wrapperChain() {
  2561. this._chain = true;
  2562. return this;
  2563. }
  2564. /**
  2565. * Extracts the value from a wrapped chainable object.
  2566. *
  2567. * @name value
  2568. * @memberOf _
  2569. * @category Chaining
  2570. * @returns {Mixed} Returns the wrapped object.
  2571. * @example
  2572. *
  2573. * _([1, 2, 3]).value();
  2574. * // => [1, 2, 3]
  2575. */
  2576. function wrapperValue() {
  2577. return this._wrapped;
  2578. }
  2579. /*--------------------------------------------------------------------------*/
  2580. extend(lodash, {
  2581. /**
  2582. * The semantic version number.
  2583. *
  2584. * @static
  2585. * @memberOf _
  2586. * @type String
  2587. */
  2588. 'VERSION': '0.1.0',
  2589. /**
  2590. * By default, Lo-Dash uses ERB-style template delimiters, change the
  2591. * following template settings to use alternative delimiters.
  2592. *
  2593. * @static
  2594. * @memberOf _
  2595. * @type Object
  2596. */
  2597. 'templateSettings': {
  2598. /**
  2599. * Used to detect `data` property values to be HTML-escaped.
  2600. *
  2601. * @static
  2602. * @memberOf _.templateSettings
  2603. * @type RegExp
  2604. */
  2605. 'escape': /<%-([\s\S]+?)%>/g,
  2606. /**
  2607. * Used to detect code to be evaluated.
  2608. *
  2609. * @static
  2610. * @memberOf _.templateSettings
  2611. * @type RegExp
  2612. */
  2613. 'evaluate': /<%([\s\S]+?)%>/g,
  2614. /**
  2615. * Used to detect `data` property values to inject.
  2616. *
  2617. * @static
  2618. * @memberOf _.templateSettings
  2619. * @type RegExp
  2620. */
  2621. 'interpolate': /<%=([\s\S]+?)%>/g
  2622. },
  2623. // assign static methods
  2624. 'after': after,
  2625. 'bind': bind,
  2626. 'bindAll': bindAll,
  2627. 'chain': chain,
  2628. 'clone': clone,
  2629. 'compact': compact,
  2630. 'compose': compose,
  2631. 'contains': contains,
  2632. 'debounce': debounce,
  2633. 'defaults': defaults,
  2634. 'defer': defer,
  2635. 'delay': delay,
  2636. 'difference': difference,
  2637. 'escape': escape,
  2638. 'every': every,
  2639. 'extend': extend,
  2640. 'filter': filter,
  2641. 'find': find,
  2642. 'first': first,
  2643. 'flatten': flatten,
  2644. 'forEach': forEach,
  2645. 'functions': functions,
  2646. 'groupBy': groupBy,
  2647. 'has': has,
  2648. 'identity': identity,
  2649. 'indexOf': indexOf,
  2650. 'initial': initial,
  2651. 'intersection': intersection,
  2652. 'invoke': invoke,
  2653. 'isArguments': isArguments,
  2654. 'isArray': isArray,
  2655. 'isBoolean': isBoolean,
  2656. 'isDate': isDate,
  2657. 'isElement': isElement,
  2658. 'isEmpty': isEmpty,
  2659. 'isEqual': isEqual,
  2660. 'isFinite': isFinite,
  2661. 'isFunction': isFunction,
  2662. 'isNaN': isNaN,
  2663. 'isNull': isNull,
  2664. 'isNumber': isNumber,
  2665. 'isObject': isObject,
  2666. 'isRegExp': isRegExp,
  2667. 'isString': isString,
  2668. 'isUndefined': isUndefined,
  2669. 'keys': keys,
  2670. 'last': last,
  2671. 'lastIndexOf': lastIndexOf,
  2672. 'map': map,
  2673. 'max': max,
  2674. 'memoize': memoize,
  2675. 'min': min,
  2676. 'mixin': mixin,
  2677. 'noConflict': noConflict,
  2678. 'once': once,
  2679. 'pick': pick,
  2680. 'pluck': pluck,
  2681. 'range': range,
  2682. 'reduce': reduce,
  2683. 'reduceRight': reduceRight,
  2684. 'reject': reject,
  2685. 'rest': rest,
  2686. 'result': result,
  2687. 'shuffle': shuffle,
  2688. 'size': size,
  2689. 'some': some,
  2690. 'sortBy': sortBy,
  2691. 'sortedIndex': sortedIndex,
  2692. 'tap': tap,
  2693. 'template': template,
  2694. 'throttle': throttle,
  2695. 'times': times,
  2696. 'toArray': toArray,
  2697. 'union': union,
  2698. 'uniq': uniq,
  2699. 'uniqueId': uniqueId,
  2700. 'values': values,
  2701. 'without': without,
  2702. 'wrap': wrap,
  2703. 'zip': zip,
  2704. // assign aliases
  2705. 'all': every,
  2706. 'any': some,
  2707. 'collect': map,
  2708. 'detect': find,
  2709. 'each': forEach,
  2710. 'foldl': reduce,
  2711. 'foldr': reduceRight,
  2712. 'head': first,
  2713. 'include': contains,
  2714. 'inject': reduce,
  2715. 'intersect': intersection,
  2716. 'methods': functions,
  2717. 'select': filter,
  2718. 'tail': rest,
  2719. 'take': first,
  2720. 'unique': uniq
  2721. });
  2722. /*--------------------------------------------------------------------------*/
  2723. // assign private `Lodash` constructor's prototype
  2724. Lodash.prototype = lodash.prototype;
  2725. // add all of the static functions to `Lodash.prototype`
  2726. mixin(lodash);
  2727. // add all mutator Array functions to the wrapper.
  2728. forEach(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
  2729. var func = ArrayProto[methodName];
  2730. lodash.prototype[methodName] = function() {
  2731. var value = this._wrapped;
  2732. func.apply(value, arguments);
  2733. // IE compatibility mode and IE < 9 have buggy Array `shift()` and `splice()`
  2734. // functions that fail to remove the last element, `object[0]`, of
  2735. // array-like-objects even though the `length` property is set to `0`.
  2736. // The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
  2737. // is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
  2738. if (value.length === 0) {
  2739. delete value[0];
  2740. }
  2741. return this._chain ? new Lodash(value).chain() : value;
  2742. };
  2743. });
  2744. // add all accessor Array functions to the wrapper.
  2745. forEach(['concat', 'join', 'slice'], function(methodName) {
  2746. var func = ArrayProto[methodName];
  2747. Lodash.prototype[methodName] = function() {
  2748. var result = func.apply(this._wrapped, arguments);
  2749. return this._chain ? new Lodash(result).chain() : result;
  2750. };
  2751. });
  2752. // add `chain` and `value` after calling to `mixin()` to avoid getting wrapped
  2753. extend(Lodash.prototype, {
  2754. 'chain': wrapperChain,
  2755. 'value': wrapperValue
  2756. });
  2757. /*--------------------------------------------------------------------------*/
  2758. // expose Lo-Dash
  2759. if (freeExports) {
  2760. // in Node.js or RingoJS v0.8.0+
  2761. if (typeof module == 'object' && module && module.exports == freeExports) {
  2762. (module.exports = lodash)._ = lodash;
  2763. }
  2764. // in Narwhal or RingoJS v0.7.0-
  2765. else {
  2766. freeExports._ = lodash;
  2767. }
  2768. }
  2769. // in a browser or Rhino
  2770. else {
  2771. // Expose Lo-Dash to the global object even when an AMD loader is present in
  2772. // case Lo-Dash was injected by a third-party script and not intended to be
  2773. // loaded as a module. The global assignment can be reverted in the Lo-Dash
  2774. // module via its `noConflict()` method.
  2775. window._ = lodash;
  2776. // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
  2777. if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
  2778. // define as an anonymous module so, through path mapping, it can be
  2779. // referenced as the "underscore" module
  2780. define(function() {
  2781. return lodash;
  2782. });
  2783. }
  2784. }
  2785. }(this));