/documentation/docs/underscore.html
HTML | 1892 lines | 1259 code | 633 blank | 0 comment | 0 complexity | b6c7530433edfb454865be08d4e16b4f MD5 | raw file
1<!DOCTYPE html> 2 3<html> 4<head> 5 <title>underscore.coffee</title> 6 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 7 <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> 8 <link rel="stylesheet" media="all" href="docco.css" /> 9</head> 10<body> 11 <div id="container"> 12 <div id="background"></div> 13 14 <ul class="sections"> 15 16 <li id="title"> 17 <div class="annotation"> 18 <h1>underscore.coffee</h1> 19 </div> 20 </li> 21 22 23 24 <li id="section-1"> 25 <div class="annotation"> 26 27 <div class="pilwrap "> 28 <a class="pilcrow" href="#section-1">¶</a> 29 </div> 30 <p><strong>Underscore.coffee 31(c) 2011 Jeremy Ashkenas, DocumentCloud Inc.</strong> 32Underscore is freely distributable under the terms of the 33<a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a>. 34Portions of Underscore are inspired by or borrowed from 35<a href="http://prototypejs.org/api">Prototype.js</a>, Oliver Steele's 36<a href="http://osteele.com">Functional</a>, and John Resig's 37<a href="http://ejohn.org">Micro-Templating</a>. 38For all details and documentation: 39<a href="http://documentcloud.github.com/underscore/">http://documentcloud.github.com/underscore/</a></p> 40<h2>Baseline setup</h2> 41 42 </div> 43 44 </li> 45 46 47 <li id="section-2"> 48 <div class="annotation"> 49 50 <div class="pilwrap "> 51 <a class="pilcrow" href="#section-2">¶</a> 52 </div> 53 <p>Establish the root object, <code>window</code> in the browser, or <code>global</code> on the server.</p> 54 55 </div> 56 57 <div class="content"><div class='highlight'><pre>root = <span class="keyword">this</span></pre></div></div> 58 59 </li> 60 61 62 <li id="section-3"> 63 <div class="annotation"> 64 65 <div class="pilwrap "> 66 <a class="pilcrow" href="#section-3">¶</a> 67 </div> 68 <p>Save the previous value of the <code>_</code> variable.</p> 69 70 </div> 71 72 <div class="content"><div class='highlight'><pre>previousUnderscore = root._</pre></div></div> 73 74 </li> 75 76 77 <li id="section-4"> 78 <div class="annotation"> 79 80 <div class="pilwrap "> 81 <a class="pilcrow" href="#section-4">¶</a> 82 </div> 83 <p>Establish the object that gets thrown to break out of a loop iteration. 84<code>StopIteration</code> is SOP on Mozilla.</p> 85 86 </div> 87 88 <div class="content"><div class='highlight'><pre>breaker = <span class="keyword">if</span> <span class="keyword">typeof</span>(StopIteration) <span class="keyword">is</span> <span class="string">'undefined'</span> <span class="keyword">then</span> <span class="string">'__break__'</span> <span class="keyword">else</span> StopIteration</pre></div></div> 89 90 </li> 91 92 93 <li id="section-5"> 94 <div class="annotation"> 95 96 <div class="pilwrap "> 97 <a class="pilcrow" href="#section-5">¶</a> 98 </div> 99 <p>Helper function to escape <strong>RegExp</strong> contents, because JS doesn't have one.</p> 100 101 </div> 102 103 <div class="content"><div class='highlight'><pre><span class="function"><span class="title">escapeRegExp</span></span> = (string) -> string.replace(<span class="regexp">/([.*+?^${}()|[\]\/\\])/g</span>, <span class="string">'\\$1'</span>)</pre></div></div> 104 105 </li> 106 107 108 <li id="section-6"> 109 <div class="annotation"> 110 111 <div class="pilwrap "> 112 <a class="pilcrow" href="#section-6">¶</a> 113 </div> 114 <p>Save bytes in the minified (but not gzipped) version:</p> 115 116 </div> 117 118 <div class="content"><div class='highlight'><pre>ArrayProto = Array.prototype 119ObjProto = Object.prototype</pre></div></div> 120 121 </li> 122 123 124 <li id="section-7"> 125 <div class="annotation"> 126 127 <div class="pilwrap "> 128 <a class="pilcrow" href="#section-7">¶</a> 129 </div> 130 <p>Create quick reference variables for speed access to core prototypes.</p> 131 132 </div> 133 134 <div class="content"><div class='highlight'><pre>slice = ArrayProto.slice 135unshift = ArrayProto.unshift 136toString = ObjProto.toString 137hasOwnProperty = ObjProto.hasOwnProperty 138propertyIsEnumerable = ObjProto.propertyIsEnumerable</pre></div></div> 139 140 </li> 141 142 143 <li id="section-8"> 144 <div class="annotation"> 145 146 <div class="pilwrap "> 147 <a class="pilcrow" href="#section-8">¶</a> 148 </div> 149 <p>All <strong>ECMA5</strong> native implementations we hope to use are declared here.</p> 150 151 </div> 152 153 <div class="content"><div class='highlight'><pre>nativeForEach = ArrayProto.forEach 154nativeMap = ArrayProto.map 155nativeReduce = ArrayProto.reduce 156nativeReduceRight = ArrayProto.reduceRight 157nativeFilter = ArrayProto.filter 158nativeEvery = ArrayProto.every 159nativeSome = ArrayProto.some 160nativeIndexOf = ArrayProto.indexOf 161nativeLastIndexOf = ArrayProto.lastIndexOf 162nativeIsArray = Array.isArray 163nativeKeys = Object.keys</pre></div></div> 164 165 </li> 166 167 168 <li id="section-9"> 169 <div class="annotation"> 170 171 <div class="pilwrap "> 172 <a class="pilcrow" href="#section-9">¶</a> 173 </div> 174 <p>Create a safe reference to the Underscore object for use below.</p> 175 176 </div> 177 178 <div class="content"><div class='highlight'><pre><span class="function"><span class="title">_</span></span> = (obj) -> <span class="keyword">new</span> wrapper(obj)</pre></div></div> 179 180 </li> 181 182 183 <li id="section-10"> 184 <div class="annotation"> 185 186 <div class="pilwrap "> 187 <a class="pilcrow" href="#section-10">¶</a> 188 </div> 189 <p>Export the Underscore object for <strong>CommonJS</strong>.</p> 190 191 </div> 192 193 <div class="content"><div class='highlight'><pre><span class="keyword">if</span> <span class="keyword">typeof</span>(exports) != <span class="string">'undefined'</span> <span class="keyword">then</span> exports._ = _</pre></div></div> 194 195 </li> 196 197 198 <li id="section-11"> 199 <div class="annotation"> 200 201 <div class="pilwrap "> 202 <a class="pilcrow" href="#section-11">¶</a> 203 </div> 204 <p>Export Underscore to global scope.</p> 205 206 </div> 207 208 <div class="content"><div class='highlight'><pre>root._ = _</pre></div></div> 209 210 </li> 211 212 213 <li id="section-12"> 214 <div class="annotation"> 215 216 <div class="pilwrap "> 217 <a class="pilcrow" href="#section-12">¶</a> 218 </div> 219 <p>Current version.</p> 220 221 </div> 222 223 <div class="content"><div class='highlight'><pre>_.VERSION = <span class="string">'1.1.0'</span></pre></div></div> 224 225 </li> 226 227 228 <li id="section-13"> 229 <div class="annotation"> 230 231 <div class="pilwrap for-h2"> 232 <a class="pilcrow" href="#section-13">¶</a> 233 </div> 234 <h2>Collection Functions</h2> 235 236 </div> 237 238 </li> 239 240 241 <li id="section-14"> 242 <div class="annotation"> 243 244 <div class="pilwrap "> 245 <a class="pilcrow" href="#section-14">¶</a> 246 </div> 247 <p>The cornerstone, an <strong>each</strong> implementation. 248Handles objects implementing <strong>forEach</strong>, arrays, and raw objects.</p> 249 250 </div> 251 252 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">each</span></span> = (obj, iterator, context) -> 253 <span class="keyword">try</span> 254 <span class="keyword">if</span> nativeForEach <span class="keyword">and</span> obj.forEach <span class="keyword">is</span> nativeForEach 255 obj.forEach iterator, context 256 <span class="keyword">else</span> <span class="keyword">if</span> _.isNumber obj.length 257 iterator.call context, obj[i], i, obj <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>..obj.length] 258 <span class="keyword">else</span> 259 iterator.call context, val, key, obj <span class="keyword">for</span> own key, val <span class="keyword">of</span> obj 260 <span class="keyword">catch</span> e 261 <span class="keyword">throw</span> e <span class="keyword">if</span> e <span class="keyword">isnt</span> breaker 262 obj</pre></div></div> 263 264 </li> 265 266 267 <li id="section-15"> 268 <div class="annotation"> 269 270 <div class="pilwrap "> 271 <a class="pilcrow" href="#section-15">¶</a> 272 </div> 273 <p>Return the results of applying the iterator to each element. Use JavaScript 2741.6's version of <strong>map</strong>, if possible.</p> 275 276 </div> 277 278 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">map</span></span> = (obj, iterator, context) -> 279 <span class="keyword">return</span> obj.map(iterator, context) <span class="keyword">if</span> nativeMap <span class="keyword">and</span> obj.map <span class="keyword">is</span> nativeMap 280 results = [] 281 _.each obj, (value, index, list) -> 282 results.push iterator.call context, value, index, list 283 results</pre></div></div> 284 285 </li> 286 287 288 <li id="section-16"> 289 <div class="annotation"> 290 291 <div class="pilwrap "> 292 <a class="pilcrow" href="#section-16">¶</a> 293 </div> 294 <p><strong>Reduce</strong> builds up a single result from a list of values. Also known as 295<strong>inject</strong>, or <strong>foldl</strong>. Uses JavaScript 1.8's version of <strong>reduce</strong>, if possible.</p> 296 297 </div> 298 299 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">reduce</span></span> = (obj, iterator, memo, context) -> 300 <span class="keyword">if</span> nativeReduce <span class="keyword">and</span> obj.reduce <span class="keyword">is</span> nativeReduce 301 iterator = _.bind iterator, context <span class="keyword">if</span> context 302 <span class="keyword">return</span> obj.reduce iterator, memo 303 _.each obj, (value, index, list) -> 304 memo = iterator.call context, memo, value, index, list 305 memo</pre></div></div> 306 307 </li> 308 309 310 <li id="section-17"> 311 <div class="annotation"> 312 313 <div class="pilwrap "> 314 <a class="pilcrow" href="#section-17">¶</a> 315 </div> 316 <p>The right-associative version of <strong>reduce</strong>, also known as <strong>foldr</strong>. Uses 317JavaScript 1.8's version of <strong>reduceRight</strong>, if available.</p> 318 319 </div> 320 321 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">reduceRight</span></span> = (obj, iterator, memo, context) -> 322 <span class="keyword">if</span> nativeReduceRight <span class="keyword">and</span> obj.reduceRight <span class="keyword">is</span> nativeReduceRight 323 iterator = _.bind iterator, context <span class="keyword">if</span> context 324 <span class="keyword">return</span> obj.reduceRight iterator, memo 325 reversed = _.clone(_.toArray(obj)).reverse() 326 _.reduce reversed, iterator, memo, context</pre></div></div> 327 328 </li> 329 330 331 <li id="section-18"> 332 <div class="annotation"> 333 334 <div class="pilwrap "> 335 <a class="pilcrow" href="#section-18">¶</a> 336 </div> 337 <p>Return the first value which passes a truth test.</p> 338 339 </div> 340 341 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">detect</span></span> = (obj, iterator, context) -> 342 result = <span class="literal">null</span> 343 _.each obj, (value, index, list) -> 344 <span class="keyword">if</span> iterator.call context, value, index, list 345 result = value 346 _.breakLoop() 347 result</pre></div></div> 348 349 </li> 350 351 352 <li id="section-19"> 353 <div class="annotation"> 354 355 <div class="pilwrap "> 356 <a class="pilcrow" href="#section-19">¶</a> 357 </div> 358 <p>Return all the elements that pass a truth test. Use JavaScript 1.6's 359<strong>filter</strong>, if it exists.</p> 360 361 </div> 362 363 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">filter</span></span> = (obj, iterator, context) -> 364 <span class="keyword">return</span> obj.filter iterator, context <span class="keyword">if</span> nativeFilter <span class="keyword">and</span> obj.filter <span class="keyword">is</span> nativeFilter 365 results = [] 366 _.each obj, (value, index, list) -> 367 results.push value <span class="keyword">if</span> iterator.call context, value, index, list 368 results</pre></div></div> 369 370 </li> 371 372 373 <li id="section-20"> 374 <div class="annotation"> 375 376 <div class="pilwrap "> 377 <a class="pilcrow" href="#section-20">¶</a> 378 </div> 379 <p>Return all the elements for which a truth test fails.</p> 380 381 </div> 382 383 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">reject</span></span> = (obj, iterator, context) -> 384 results = [] 385 _.each obj, (value, index, list) -> 386 results.push value <span class="keyword">if</span> <span class="keyword">not</span> iterator.call context, value, index, list 387 results</pre></div></div> 388 389 </li> 390 391 392 <li id="section-21"> 393 <div class="annotation"> 394 395 <div class="pilwrap "> 396 <a class="pilcrow" href="#section-21">¶</a> 397 </div> 398 <p>Determine whether all of the elements match a truth test. Delegate to 399JavaScript 1.6's <strong>every</strong>, if it is present.</p> 400 401 </div> 402 403 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">every</span></span> = (obj, iterator, context) -> 404 iterator ||= _.identity 405 <span class="keyword">return</span> obj.every iterator, context <span class="keyword">if</span> nativeEvery <span class="keyword">and</span> obj.every <span class="keyword">is</span> nativeEvery 406 result = <span class="literal">true</span> 407 _.each obj, (value, index, list) -> 408 _.breakLoop() <span class="keyword">unless</span> (result = result <span class="keyword">and</span> iterator.call(context, value, index, list)) 409 result</pre></div></div> 410 411 </li> 412 413 414 <li id="section-22"> 415 <div class="annotation"> 416 417 <div class="pilwrap "> 418 <a class="pilcrow" href="#section-22">¶</a> 419 </div> 420 <p>Determine if at least one element in the object matches a truth test. Use 421JavaScript 1.6's <strong>some</strong>, if it exists.</p> 422 423 </div> 424 425 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">some</span></span> = (obj, iterator, context) -> 426 iterator ||= _.identity 427 <span class="keyword">return</span> obj.some iterator, context <span class="keyword">if</span> nativeSome <span class="keyword">and</span> obj.some <span class="keyword">is</span> nativeSome 428 result = <span class="literal">false</span> 429 _.each obj, (value, index, list) -> 430 _.breakLoop() <span class="keyword">if</span> (result = iterator.call(context, value, index, list)) 431 result</pre></div></div> 432 433 </li> 434 435 436 <li id="section-23"> 437 <div class="annotation"> 438 439 <div class="pilwrap "> 440 <a class="pilcrow" href="#section-23">¶</a> 441 </div> 442 <p>Determine if a given value is included in the array or object, 443based on <code>===</code>.</p> 444 445 </div> 446 447 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">include</span></span> = (obj, target) -> 448 <span class="keyword">return</span> _.indexOf(obj, target) <span class="keyword">isnt</span> -<span class="number">1</span> <span class="keyword">if</span> nativeIndexOf <span class="keyword">and</span> obj.indexOf <span class="keyword">is</span> nativeIndexOf 449 <span class="keyword">return</span> <span class="literal">true</span> <span class="keyword">for</span> own key, val <span class="keyword">of</span> obj <span class="keyword">when</span> val <span class="keyword">is</span> target 450 <span class="literal">false</span></pre></div></div> 451 452 </li> 453 454 455 <li id="section-24"> 456 <div class="annotation"> 457 458 <div class="pilwrap "> 459 <a class="pilcrow" href="#section-24">¶</a> 460 </div> 461 <p>Invoke a method with arguments on every item in a collection.</p> 462 463 </div> 464 465 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">invoke</span></span> = (obj, method) -> 466 args = _.rest arguments, <span class="number">2</span> 467 (<span class="keyword">if</span> method <span class="keyword">then</span> val[method] <span class="keyword">else</span> val).apply(val, args) <span class="keyword">for</span> val <span class="keyword">in</span> obj</pre></div></div> 468 469 </li> 470 471 472 <li id="section-25"> 473 <div class="annotation"> 474 475 <div class="pilwrap "> 476 <a class="pilcrow" href="#section-25">¶</a> 477 </div> 478 <p>Convenience version of a common use case of <strong>map</strong>: fetching a property.</p> 479 480 </div> 481 482 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">pluck</span></span> = (obj, key) -> 483 _.map(obj, (val) -> val[key])</pre></div></div> 484 485 </li> 486 487 488 <li id="section-26"> 489 <div class="annotation"> 490 491 <div class="pilwrap "> 492 <a class="pilcrow" href="#section-26">¶</a> 493 </div> 494 <p>Return the maximum item or (item-based computation).</p> 495 496 </div> 497 498 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">max</span></span> = (obj, iterator, context) -> 499 <span class="keyword">return</span> Math.max.apply(Math, obj) <span class="keyword">if</span> <span class="keyword">not</span> iterator <span class="keyword">and</span> _.isArray(obj) 500 result = computed: -Infinity 501 _.each obj, (value, index, list) -> 502 computed = <span class="keyword">if</span> iterator <span class="keyword">then</span> iterator.call(context, value, index, list) <span class="keyword">else</span> value 503 computed >= result.computed <span class="keyword">and</span> (result = {value: value, computed: computed}) 504 result.value</pre></div></div> 505 506 </li> 507 508 509 <li id="section-27"> 510 <div class="annotation"> 511 512 <div class="pilwrap "> 513 <a class="pilcrow" href="#section-27">¶</a> 514 </div> 515 <p>Return the minimum element (or element-based computation).</p> 516 517 </div> 518 519 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">min</span></span> = (obj, iterator, context) -> 520 <span class="keyword">return</span> Math.min.apply(Math, obj) <span class="keyword">if</span> <span class="keyword">not</span> iterator <span class="keyword">and</span> _.isArray(obj) 521 result = computed: Infinity 522 _.each obj, (value, index, list) -> 523 computed = <span class="keyword">if</span> iterator <span class="keyword">then</span> iterator.call(context, value, index, list) <span class="keyword">else</span> value 524 computed < result.computed <span class="keyword">and</span> (result = {value: value, computed: computed}) 525 result.value</pre></div></div> 526 527 </li> 528 529 530 <li id="section-28"> 531 <div class="annotation"> 532 533 <div class="pilwrap "> 534 <a class="pilcrow" href="#section-28">¶</a> 535 </div> 536 <p>Sort the object's values by a criterion produced by an iterator.</p> 537 538 </div> 539 540 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">sortBy</span></span> = (obj, iterator, context) -> 541 _.pluck(((_.map obj, (value, index, list) -> 542 {value: value, criteria: iterator.call(context, value, index, list)} 543 ).sort((left, right) -> 544 a = left.criteria; b = right.criteria 545 <span class="keyword">if</span> a < b <span class="keyword">then</span> -<span class="number">1</span> <span class="keyword">else</span> <span class="keyword">if</span> a > b <span class="keyword">then</span> <span class="number">1</span> <span class="keyword">else</span> <span class="number">0</span> 546 )), <span class="string">'value'</span>)</pre></div></div> 547 548 </li> 549 550 551 <li id="section-29"> 552 <div class="annotation"> 553 554 <div class="pilwrap "> 555 <a class="pilcrow" href="#section-29">¶</a> 556 </div> 557 <p>Use a comparator function to figure out at what index an object should 558be inserted so as to maintain order. Uses binary search.</p> 559 560 </div> 561 562 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">sortedIndex</span></span> = (array, obj, iterator) -> 563 iterator ||= _.identity 564 low = <span class="number">0</span> 565 high = array.length 566 <span class="keyword">while</span> low < high 567 mid = (low + high) >> <span class="number">1</span> 568 <span class="keyword">if</span> iterator(array[mid]) < iterator(obj) <span class="keyword">then</span> low = mid + <span class="number">1</span> <span class="keyword">else</span> high = mid 569 low</pre></div></div> 570 571 </li> 572 573 574 <li id="section-30"> 575 <div class="annotation"> 576 577 <div class="pilwrap "> 578 <a class="pilcrow" href="#section-30">¶</a> 579 </div> 580 <p>Convert anything iterable into a real, live array.</p> 581 582 </div> 583 584 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">toArray</span></span> = (iterable) -> 585 <span class="keyword">return</span> [] <span class="keyword">if</span> (!iterable) 586 <span class="keyword">return</span> iterable.toArray() <span class="keyword">if</span> (iterable.toArray) 587 <span class="keyword">return</span> iterable <span class="keyword">if</span> (_.isArray(iterable)) 588 <span class="keyword">return</span> slice.call(iterable) <span class="keyword">if</span> (_.isArguments(iterable)) 589 _.values(iterable)</pre></div></div> 590 591 </li> 592 593 594 <li id="section-31"> 595 <div class="annotation"> 596 597 <div class="pilwrap "> 598 <a class="pilcrow" href="#section-31">¶</a> 599 </div> 600 <p>Return the number of elements in an object.</p> 601 602 </div> 603 604 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">size</span></span> = (obj) -> _.toArray(obj).length</pre></div></div> 605 606 </li> 607 608 609 <li id="section-32"> 610 <div class="annotation"> 611 612 <div class="pilwrap for-h2"> 613 <a class="pilcrow" href="#section-32">¶</a> 614 </div> 615 <h2>Array Functions</h2> 616 617 </div> 618 619 </li> 620 621 622 <li id="section-33"> 623 <div class="annotation"> 624 625 <div class="pilwrap "> 626 <a class="pilcrow" href="#section-33">¶</a> 627 </div> 628 <p>Get the first element of an array. Passing <code>n</code> will return the first N 629values in the array. Aliased as <strong>head</strong>. The <code>guard</code> check allows it to work 630with <strong>map</strong>.</p> 631 632 </div> 633 634 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">first</span></span> = (array, n, guard) -> 635 <span class="keyword">if</span> n <span class="keyword">and</span> <span class="keyword">not</span> guard <span class="keyword">then</span> slice.call(array, <span class="number">0</span>, n) <span class="keyword">else</span> array[<span class="number">0</span>]</pre></div></div> 636 637 </li> 638 639 640 <li id="section-34"> 641 <div class="annotation"> 642 643 <div class="pilwrap "> 644 <a class="pilcrow" href="#section-34">¶</a> 645 </div> 646 <p>Returns everything but the first entry of the array. Aliased as <strong>tail</strong>. 647Especially useful on the arguments object. Passing an <code>index</code> will return 648the rest of the values in the array from that index onward. The <code>guard</code> 649check allows it to work with <strong>map</strong>.</p> 650 651 </div> 652 653 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">rest</span></span> = (array, index, guard) -> 654 slice.call(array, <span class="keyword">if</span> _.isUndefined(index) <span class="keyword">or</span> guard <span class="keyword">then</span> <span class="number">1</span> <span class="keyword">else</span> index)</pre></div></div> 655 656 </li> 657 658 659 <li id="section-35"> 660 <div class="annotation"> 661 662 <div class="pilwrap "> 663 <a class="pilcrow" href="#section-35">¶</a> 664 </div> 665 <p>Get the last element of an array.</p> 666 667 </div> 668 669 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">last</span></span> = (array) -> array[array.length - <span class="number">1</span>]</pre></div></div> 670 671 </li> 672 673 674 <li id="section-36"> 675 <div class="annotation"> 676 677 <div class="pilwrap "> 678 <a class="pilcrow" href="#section-36">¶</a> 679 </div> 680 <p>Trim out all falsy values from an array.</p> 681 682 </div> 683 684 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">compact</span></span> = (array) -> item <span class="keyword">for</span> item <span class="keyword">in</span> array <span class="keyword">when</span> item</pre></div></div> 685 686 </li> 687 688 689 <li id="section-37"> 690 <div class="annotation"> 691 692 <div class="pilwrap "> 693 <a class="pilcrow" href="#section-37">¶</a> 694 </div> 695 <p>Return a completely flattened version of an array.</p> 696 697 </div> 698 699 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">flatten</span></span> = (array) -> 700 _.reduce array, (memo, value) -> 701 <span class="keyword">return</span> memo.concat(_.flatten(value)) <span class="keyword">if</span> _.isArray value 702 memo.push value 703 memo 704 , []</pre></div></div> 705 706 </li> 707 708 709 <li id="section-38"> 710 <div class="annotation"> 711 712 <div class="pilwrap "> 713 <a class="pilcrow" href="#section-38">¶</a> 714 </div> 715 <p>Return a version of the array that does not contain the specified value(s).</p> 716 717 </div> 718 719 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">without</span></span> = (array) -> 720 values = _.rest arguments 721 val <span class="keyword">for</span> val <span class="keyword">in</span> _.toArray(array) <span class="keyword">when</span> <span class="keyword">not</span> _.include values, val</pre></div></div> 722 723 </li> 724 725 726 <li id="section-39"> 727 <div class="annotation"> 728 729 <div class="pilwrap "> 730 <a class="pilcrow" href="#section-39">¶</a> 731 </div> 732 <p>Produce a duplicate-free version of the array. If the array has already 733been sorted, you have the option of using a faster algorithm.</p> 734 735 </div> 736 737 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">uniq</span></span> = (array, isSorted) -> 738 memo = [] 739 <span class="keyword">for</span> el, i <span class="keyword">in</span> _.toArray array 740 memo.push el <span class="keyword">if</span> i <span class="keyword">is</span> <span class="number">0</span> || (<span class="keyword">if</span> isSorted <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">then</span> _.last(memo) <span class="keyword">isnt</span> el <span class="keyword">else</span> <span class="keyword">not</span> _.include(memo, el)) 741 memo</pre></div></div> 742 743 </li> 744 745 746 <li id="section-40"> 747 <div class="annotation"> 748 749 <div class="pilwrap "> 750 <a class="pilcrow" href="#section-40">¶</a> 751 </div> 752 <p>Produce an array that contains every item shared between all the 753passed-in arrays.</p> 754 755 </div> 756 757 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">intersect</span></span> = (array) -> 758 rest = _.rest arguments 759 _.select _.uniq(array), (item) -> 760 _.all rest, (other) -> 761 _.indexOf(other, item) >= <span class="number">0</span></pre></div></div> 762 763 </li> 764 765 766 <li id="section-41"> 767 <div class="annotation"> 768 769 <div class="pilwrap "> 770 <a class="pilcrow" href="#section-41">¶</a> 771 </div> 772 <p>Zip together multiple lists into a single array -- elements that share 773an index go together.</p> 774 775 </div> 776 777 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">zip</span></span> = -> 778 length = _.max _.pluck arguments, <span class="string">'length'</span> 779 results = <span class="keyword">new</span> Array length 780 <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>..length] 781 results[i] = _.pluck arguments, String i 782 results</pre></div></div> 783 784 </li> 785 786 787 <li id="section-42"> 788 <div class="annotation"> 789 790 <div class="pilwrap "> 791 <a class="pilcrow" href="#section-42">¶</a> 792 </div> 793 <p>If the browser doesn't supply us with <strong>indexOf</strong> (I'm looking at you, MSIE), 794we need this function. Return the position of the first occurrence of an 795item in an array, or -1 if the item is not included in the array.</p> 796 797 </div> 798 799 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">indexOf</span></span> = (array, item) -> 800 <span class="keyword">return</span> array.indexOf item <span class="keyword">if</span> nativeIndexOf <span class="keyword">and</span> array.indexOf <span class="keyword">is</span> nativeIndexOf 801 i = <span class="number">0</span>; l = array.length 802 <span class="keyword">while</span> l - i 803 <span class="keyword">if</span> array[i] <span class="keyword">is</span> item <span class="keyword">then</span> <span class="keyword">return</span> i <span class="keyword">else</span> i++ 804 -<span class="number">1</span></pre></div></div> 805 806 </li> 807 808 809 <li id="section-43"> 810 <div class="annotation"> 811 812 <div class="pilwrap "> 813 <a class="pilcrow" href="#section-43">¶</a> 814 </div> 815 <p>Provide JavaScript 1.6's <strong>lastIndexOf</strong>, delegating to the native function, 816if possible.</p> 817 818 </div> 819 820 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">lastIndexOf</span></span> = (array, item) -> 821 <span class="keyword">return</span> array.lastIndexOf(item) <span class="keyword">if</span> nativeLastIndexOf <span class="keyword">and</span> array.lastIndexOf <span class="keyword">is</span> nativeLastIndexOf 822 i = array.length 823 <span class="keyword">while</span> i 824 <span class="keyword">if</span> array[i] <span class="keyword">is</span> item <span class="keyword">then</span> <span class="keyword">return</span> i <span class="keyword">else</span> i-- 825 -<span class="number">1</span></pre></div></div> 826 827 </li> 828 829 830 <li id="section-44"> 831 <div class="annotation"> 832 833 <div class="pilwrap "> 834 <a class="pilcrow" href="#section-44">¶</a> 835 </div> 836 <p>Generate an integer Array containing an arithmetic progression. A port of 837<a href="http://docs.python.org/library/functions.html#range">the native Python <strong>range</strong> function</a>.</p> 838 839 </div> 840 841 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">range</span></span> = (start, stop, step) -> 842 a = arguments 843 solo = a.length <= <span class="number">1</span> 844 i = start = <span class="keyword">if</span> solo <span class="keyword">then</span> <span class="number">0</span> <span class="keyword">else</span> a[<span class="number">0</span>] 845 stop = <span class="keyword">if</span> solo <span class="keyword">then</span> a[<span class="number">0</span>] <span class="keyword">else</span> a[<span class="number">1</span>] 846 step = a[<span class="number">2</span>] <span class="keyword">or</span> <span class="number">1</span> 847 len = Math.ceil((stop - start) / step) 848 <span class="keyword">return</span> [] <span class="keyword">if</span> len <= <span class="number">0</span> 849 range = <span class="keyword">new</span> Array len 850 idx = <span class="number">0</span> 851 <span class="keyword">loop</span> 852 <span class="keyword">return</span> range <span class="keyword">if</span> (<span class="keyword">if</span> step > <span class="number">0</span> <span class="keyword">then</span> i - stop <span class="keyword">else</span> stop - i) >= <span class="number">0</span> 853 range[idx] = i 854 idx++ 855 i+= step</pre></div></div> 856 857 </li> 858 859 860 <li id="section-45"> 861 <div class="annotation"> 862 863 <div class="pilwrap for-h2"> 864 <a class="pilcrow" href="#section-45">¶</a> 865 </div> 866 <h2>Function Functions</h2> 867 868 </div> 869 870 </li> 871 872 873 <li id="section-46"> 874 <div class="annotation"> 875 876 <div class="pilwrap "> 877 <a class="pilcrow" href="#section-46">¶</a> 878 </div> 879 <p>Create a function bound to a given object (assigning <code>this</code>, and arguments, 880optionally). Binding with arguments is also known as <strong>curry</strong>.</p> 881 882 </div> 883 884 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">bind</span></span> = (func, obj) -> 885 args = _.rest arguments, <span class="number">2</span> 886 -> func.apply obj <span class="keyword">or</span> root, args.concat arguments</pre></div></div> 887 888 </li> 889 890 891 <li id="section-47"> 892 <div class="annotation"> 893 894 <div class="pilwrap "> 895 <a class="pilcrow" href="#section-47">¶</a> 896 </div> 897 <p>Bind all of an object's methods to that object. Useful for ensuring that 898all callbacks defined on an object belong to it.</p> 899 900 </div> 901 902 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">bindAll</span></span> = (obj) -> 903 funcs = <span class="keyword">if</span> arguments.length > <span class="number">1</span> <span class="keyword">then</span> _.rest(arguments) <span class="keyword">else</span> _.functions(obj) 904 _.each funcs, (f) -> obj[f] = _.bind obj[f], obj 905 obj</pre></div></div> 906 907 </li> 908 909 910 <li id="section-48"> 911 <div class="annotation"> 912 913 <div class="pilwrap "> 914 <a class="pilcrow" href="#section-48">¶</a> 915 </div> 916 <p>Delays a function for the given number of milliseconds, and then calls 917it with the arguments supplied.</p> 918 919 </div> 920 921 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">delay</span></span> = (func, wait) -> 922 args = _.rest arguments, <span class="number">2</span> 923 setTimeout((-> func.apply(func, args)), wait)</pre></div></div> 924 925 </li> 926 927 928 <li id="section-49"> 929 <div class="annotation"> 930 931 <div class="pilwrap "> 932 <a class="pilcrow" href="#section-49">¶</a> 933 </div> 934 <p>Memoize an expensive function by storing its results.</p> 935 936 </div> 937 938 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">memoize</span></span> = (func, hasher) -> 939 memo = {} 940 hasher <span class="keyword">or</span>= _.identity 941 -> 942 key = hasher.apply <span class="keyword">this</span>, arguments 943 <span class="keyword">return</span> memo[key] <span class="keyword">if</span> key <span class="keyword">of</span> memo 944 memo[key] = func.apply <span class="keyword">this</span>, arguments</pre></div></div> 945 946 </li> 947 948 949 <li id="section-50"> 950 <div class="annotation"> 951 952 <div class="pilwrap "> 953 <a class="pilcrow" href="#section-50">¶</a> 954 </div> 955 <p>Defers a function, scheduling it to run after the current call stack has 956cleared.</p> 957 958 </div> 959 960 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">defer</span></span> = (func) -> 961 _.delay.apply _, [func, <span class="number">1</span>].concat _.rest arguments</pre></div></div> 962 963 </li> 964 965 966 <li id="section-51"> 967 <div class="annotation"> 968 969 <div class="pilwrap "> 970 <a class="pilcrow" href="#section-51">¶</a> 971 </div> 972 <p>Returns the first function passed as an argument to the second, 973allowing you to adjust arguments, run code before and after, and 974conditionally execute the original function.</p> 975 976 </div> 977 978 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">wrap</span></span> = (func, wrapper) -> 979 -> wrapper.apply wrapper, [func].concat arguments</pre></div></div> 980 981 </li> 982 983 984 <li id="section-52"> 985 <div class="annotation"> 986 987 <div class="pilwrap "> 988 <a class="pilcrow" href="#section-52">¶</a> 989 </div> 990 <p>Returns a function that is the composition of a list of functions, each 991consuming the return value of the function that follows.</p> 992 993 </div> 994 995 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">compose</span></span> = -> 996 funcs = arguments 997 -> 998 args = arguments 999 <span class="keyword">for</span> i <span class="keyword">in</span> [funcs.length - <span class="number">1.</span><span class="number">.0</span>] <span class="keyword">by</span> -<span class="number">1</span> 1000 args = [funcs[i].apply(<span class="keyword">this</span>, args)] 1001 args[<span class="number">0</span>]</pre></div></div> 1002 1003 </li> 1004 1005 1006 <li id="section-53"> 1007 <div class="annotation"> 1008 1009 <div class="pilwrap for-h2"> 1010 <a class="pilcrow" href="#section-53">¶</a> 1011 </div> 1012 <h2>Object Functions</h2> 1013 1014 </div> 1015 1016 </li> 1017 1018 1019 <li id="section-54"> 1020 <div class="annotation"> 1021 1022 <div class="pilwrap "> 1023 <a class="pilcrow" href="#section-54">¶</a> 1024 </div> 1025 <p>Retrieve the names of an object's properties.</p> 1026 1027 </div> 1028 1029 <div class="content"><div class='highlight'><pre>_.keys = nativeKeys <span class="keyword">or</span> (obj) -> 1030 <span class="keyword">return</span> _.range <span class="number">0</span>, obj.length <span class="keyword">if</span> _.isArray(obj) 1031 key <span class="keyword">for</span> key, val <span class="keyword">of</span> obj</pre></div></div> 1032 1033 </li> 1034 1035 1036 <li id="section-55"> 1037 <div class="annotation"> 1038 1039 <div class="pilwrap "> 1040 <a class="pilcrow" href="#section-55">¶</a> 1041 </div> 1042 <p>Retrieve the values of an object's properties.</p> 1043 1044 </div> 1045 1046 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">values</span></span> = (obj) -> 1047 _.map obj, _.identity</pre></div></div> 1048 1049 </li> 1050 1051 1052 <li id="section-56"> 1053 <div class="annotation"> 1054 1055 <div class="pilwrap "> 1056 <a class="pilcrow" href="#section-56">¶</a> 1057 </div> 1058 <p>Return a sorted list of the function names available in Underscore.</p> 1059 1060 </div> 1061 1062 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">functions</span></span> = (obj) -> 1063 _.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()</pre></div></div> 1064 1065 </li> 1066 1067 1068 <li id="section-57"> 1069 <div class="annotation"> 1070 1071 <div class="pilwrap "> 1072 <a class="pilcrow" href="#section-57">¶</a> 1073 </div> 1074 <p>Extend a given object with all of the properties in a source object.</p> 1075 1076 </div> 1077 1078 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">extend</span></span> = (obj) -> 1079 <span class="keyword">for</span> source <span class="keyword">in</span> _.rest(arguments) 1080 obj[key] = val <span class="keyword">for</span> key, val <span class="keyword">of</span> source 1081 obj</pre></div></div> 1082 1083 </li> 1084 1085 1086 <li id="section-58"> 1087 <div class="annotation"> 1088 1089 <div class="pilwrap "> 1090 <a class="pilcrow" href="#section-58">¶</a> 1091 </div> 1092 <p>Create a (shallow-cloned) duplicate of an object.</p> 1093 1094 </div> 1095 1096 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">clone</span></span> = (obj) -> 1097 <span class="keyword">return</span> obj.slice <span class="number">0</span> <span class="keyword">if</span> _.isArray obj 1098 _.extend {}, obj</pre></div></div> 1099 1100 </li> 1101 1102 1103 <li id="section-59"> 1104 <div class="annotation"> 1105 1106 <div class="pilwrap "> 1107 <a class="pilcrow" href="#section-59">¶</a> 1108 </div> 1109 <p>Invokes interceptor with the obj, and then returns obj. 1110The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.</p> 1111 1112 </div> 1113 1114 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">tap</span></span> = (obj, interceptor) -> 1115 interceptor obj 1116 obj</pre></div></div> 1117 1118 </li> 1119 1120 1121 <li id="section-60"> 1122 <div class="annotation"> 1123 1124 <div class="pilwrap "> 1125 <a class="pilcrow" href="#section-60">¶</a> 1126 </div> 1127 <p>Perform a deep comparison to check if two objects are equal.</p> 1128 1129 </div> 1130 1131 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isEqual</span></span> = (a, b) -></pre></div></div> 1132 1133 </li> 1134 1135 1136 <li id="section-61"> 1137 <div class="annotation"> 1138 1139 <div class="pilwrap "> 1140 <a class="pilcrow" href="#section-61">¶</a> 1141 </div> 1142 <p>Check object identity.</p> 1143 1144 </div> 1145 1146 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">true</span> <span class="keyword">if</span> a <span class="keyword">is</span> b</pre></div></div> 1147 1148 </li> 1149 1150 1151 <li id="section-62"> 1152 <div class="annotation"> 1153 1154 <div class="pilwrap "> 1155 <a class="pilcrow" href="#section-62">¶</a> 1156 </div> 1157 <p>Different types?</p> 1158 1159 </div> 1160 1161 <div class="content"><div class='highlight'><pre> atype = <span class="keyword">typeof</span>(a); btype = <span class="keyword">typeof</span>(b) 1162 <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">if</span> atype <span class="keyword">isnt</span> btype</pre></div></div> 1163 1164 </li> 1165 1166 1167 <li id="section-63"> 1168 <div class="annotation"> 1169 1170 <div class="pilwrap "> 1171 <a class="pilcrow" href="#section-63">¶</a> 1172 </div> 1173 <p>Basic equality test (watch out for coercions).</p> 1174 1175 </div> 1176 1177 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">true</span> <span class="keyword">if</span> `<span class="javascript">a == b</span>`</pre></div></div> 1178 1179 </li> 1180 1181 1182 <li id="section-64"> 1183 <div class="annotation"> 1184 1185 <div class="pilwrap "> 1186 <a class="pilcrow" href="#section-64">¶</a> 1187 </div> 1188 <p>One is falsy and the other truthy.</p> 1189 1190 </div> 1191 1192 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">if</span> (!a <span class="keyword">and</span> b) <span class="keyword">or</span> (a <span class="keyword">and</span> !b)</pre></div></div> 1193 1194 </li> 1195 1196 1197 <li id="section-65"> 1198 <div class="annotation"> 1199 1200 <div class="pilwrap "> 1201 <a class="pilcrow" href="#section-65">¶</a> 1202 </div> 1203 <p>One of them implements an <code>isEqual()</code>?</p> 1204 1205 </div> 1206 1207 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> a.isEqual(b) <span class="keyword">if</span> a.isEqual</pre></div></div> 1208 1209 </li> 1210 1211 1212 <li id="section-66"> 1213 <div class="annotation"> 1214 1215 <div class="pilwrap "> 1216 <a class="pilcrow" href="#section-66">¶</a> 1217 </div> 1218 <p>Check dates' integer values.</p> 1219 1220 </div> 1221 1222 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> a.getTime() <span class="keyword">is</span> b.getTime() <span class="keyword">if</span> _.isDate(a) <span class="keyword">and</span> _.isDate(b)</pre></div></div> 1223 1224 </li> 1225 1226 1227 <li id="section-67"> 1228 <div class="annotation"> 1229 1230 <div class="pilwrap "> 1231 <a class="pilcrow" href="#section-67">¶</a> 1232 </div> 1233 <p>Both are NaN?</p> 1234 1235 </div> 1236 1237 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">if</span> _.isNaN(a) <span class="keyword">and</span> _.isNaN(b)</pre></div></div> 1238 1239 </li> 1240 1241 1242 <li id="section-68"> 1243 <div class="annotation"> 1244 1245 <div class="pilwrap "> 1246 <a class="pilcrow" href="#section-68">¶</a> 1247 </div> 1248 <p>Compare regular expressions.</p> 1249 1250 </div> 1251 1252 <div class="content"><div class='highlight'><pre> <span class="keyword">if</span> _.isRegExp(a) <span class="keyword">and</span> _.isRegExp(b) 1253 <span class="keyword">return</span> a.source <span class="keyword">is</span> b.source <span class="keyword">and</span> 1254 a.global <span class="keyword">is</span> b.global <span class="keyword">and</span> 1255 a.ignoreCase <span class="keyword">is</span> b.ignoreCase <span class="keyword">and</span> 1256 a.multiline <span class="keyword">is</span> b.multiline</pre></div></div> 1257 1258 </li> 1259 1260 1261 <li id="section-69"> 1262 <div class="annotation"> 1263 1264 <div class="pilwrap "> 1265 <a class="pilcrow" href="#section-69">¶</a> 1266 </div> 1267 <p>If a is not an object by this point, we can't handle it.</p> 1268 1269 </div> 1270 1271 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">if</span> atype <span class="keyword">isnt</span> <span class="string">'object'</span></pre></div></div> 1272 1273 </li> 1274 1275 1276 <li id="section-70"> 1277 <div class="annotation"> 1278 1279 <div class="pilwrap "> 1280 <a class="pilcrow" href="#section-70">¶</a> 1281 </div> 1282 <p>Check for different array lengths before comparing contents.</p> 1283 1284 </div> 1285 1286 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">if</span> a.length <span class="keyword">and</span> (a.length <span class="keyword">isnt</span> b.length)</pre></div></div> 1287 1288 </li> 1289 1290 1291 <li id="section-71"> 1292 <div class="annotation"> 1293 1294 <div class="pilwrap "> 1295 <a class="pilcrow" href="#section-71">¶</a> 1296 </div> 1297 <p>Nothing else worked, deep compare the contents.</p> 1298 1299 </div> 1300 1301 <div class="content"><div class='highlight'><pre> aKeys = _.keys(a); bKeys = _.keys(b)</pre></div></div> 1302 1303 </li> 1304 1305 1306 <li id="section-72"> 1307 <div class="annotation"> 1308 1309 <div class="pilwrap "> 1310 <a class="pilcrow" href="#section-72">¶</a> 1311 </div> 1312 <p>Different object sizes?</p> 1313 1314 </div> 1315 1316 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">if</span> aKeys.length <span class="keyword">isnt</span> bKeys.length</pre></div></div> 1317 1318 </li> 1319 1320 1321 <li id="section-73"> 1322 <div class="annotation"> 1323 1324 <div class="pilwrap "> 1325 <a class="pilcrow" href="#section-73">¶</a> 1326 </div> 1327 <p>Recursive comparison of contents.</p> 1328 1329 </div> 1330 1331 <div class="content"><div class='highlight'><pre> <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">for</span> key, val <span class="keyword">of</span> a <span class="keyword">when</span> !(key <span class="keyword">of</span> b) <span class="keyword">or</span> !_.isEqual(val, b[key]) 1332 <span class="literal">true</span></pre></div></div> 1333 1334 </li> 1335 1336 1337 <li id="section-74"> 1338 <div class="annotation"> 1339 1340 <div class="pilwrap "> 1341 <a class="pilcrow" href="#section-74">¶</a> 1342 </div> 1343 <p>Is a given array or object empty?</p> 1344 1345 </div> 1346 1347 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isEmpty</span></span> = (obj) -> 1348 <span class="keyword">return</span> obj.length <span class="keyword">is</span> <span class="number">0</span> <span class="keyword">if</span> _.isArray(obj) <span class="keyword">or</span> _.isString(obj) 1349 <span class="keyword">return</span> <span class="literal">false</span> <span class="keyword">for</span> own key <span class="keyword">of</span> obj 1350 <span class="literal">true</span></pre></div></div> 1351 1352 </li> 1353 1354 1355 <li id="section-75"> 1356 <div class="annotation"> 1357 1358 <div class="pilwrap "> 1359 <a class="pilcrow" href="#section-75">¶</a> 1360 </div> 1361 <p>Is a given value a DOM element?</p> 1362 1363 </div> 1364 1365 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isElement</span></span> = (obj) -> obj <span class="keyword">and</span> obj.nodeType <span class="keyword">is</span> <span class="number">1</span></pre></div></div> 1366 1367 </li> 1368 1369 1370 <li id="section-76"> 1371 <div class="annotation"> 1372 1373 <div class="pilwrap "> 1374 <a class="pilcrow" href="#section-76">¶</a> 1375 </div> 1376 <p>Is a given value an array?</p> 1377 1378 </div> 1379 1380 <div class="content"><div class='highlight'><pre>_.isArray = nativeIsArray <span class="keyword">or</span> (obj) -> !!(obj <span class="keyword">and</span> obj.concat <span class="keyword">and</span> obj.unshift <span class="keyword">and</span> <span class="keyword">not</span> obj.callee)</pre></div></div> 1381 1382 </li> 1383 1384 1385 <li id="section-77"> 1386 <div class="annotation"> 1387 1388 <div class="pilwrap "> 1389 <a class="pilcrow" href="#section-77">¶</a> 1390 </div> 1391 <p>Is a given variable an arguments object?</p> 1392 1393 </div> 1394 1395 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isArguments</span></span> = (obj) -> obj <span class="keyword">and</span> obj.callee</pre></div></div> 1396 1397 </li> 1398 1399 1400 <li id="section-78"> 1401 <div class="annotation"> 1402 1403 <div class="pilwrap "> 1404 <a class="pilcrow" href="#section-78">¶</a> 1405 </div> 1406 <p>Is the given value a function?</p> 1407 1408 </div> 1409 1410 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isFunction</span></span> = (obj) -> !!(obj <span class="keyword">and</span> obj.constructor <span class="keyword">and</span> obj.call <span class="keyword">and</span> obj.apply)</pre></div></div> 1411 1412 </li> 1413 1414 1415 <li id="section-79"> 1416 <div class="annotation"> 1417 1418 <div class="pilwrap "> 1419 <a class="pilcrow" href="#section-79">¶</a> 1420 </div> 1421 <p>Is the given value a string?</p> 1422 1423 </div> 1424 1425 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isString</span></span> = (obj) -> !!(obj <span class="keyword">is</span> <span class="string">''</span> <span class="keyword">or</span> (obj <span class="keyword">and</span> obj.charCodeAt <span class="keyword">and</span> obj.substr))</pre></div></div> 1426 1427 </li> 1428 1429 1430 <li id="section-80"> 1431 <div class="annotation"> 1432 1433 <div class="pilwrap "> 1434 <a class="pilcrow" href="#section-80">¶</a> 1435 </div> 1436 <p>Is a given value a number?</p> 1437 1438 </div> 1439 1440 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isNumber</span></span> = (obj) -> (obj <span class="keyword">is</span> +obj) <span class="keyword">or</span> toString.call(obj) <span class="keyword">is</span> <span class="string">'[object Number]'</span></pre></div></div> 1441 1442 </li> 1443 1444 1445 <li id="section-81"> 1446 <div class="annotation"> 1447 1448 <div class="pilwrap "> 1449 <a class="pilcrow" href="#section-81">¶</a> 1450 </div> 1451 <p>Is a given value a boolean?</p> 1452 1453 </div> 1454 1455 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isBoolean</span></span> = (obj) -> obj <span class="keyword">is</span> <span class="literal">true</span> <span class="keyword">or</span> obj <span class="keyword">is</span> <span class="literal">false</span></pre></div></div> 1456 1457 </li> 1458 1459 1460 <li id="section-82"> 1461 <div class="annotation"> 1462 1463 <div class="pilwrap "> 1464 <a class="pilcrow" href="#section-82">¶</a> 1465 </div> 1466 <p>Is a given value a Date?</p> 1467 1468 </div> 1469 1470 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isDate</span></span> = (obj) -> !!(obj <span class="keyword">and</span> obj.getTimezoneOffset <span class="keyword">and</span> obj.setUTCFullYear)</pre></div></div> 1471 1472 </li> 1473 1474 1475 <li id="section-83"> 1476 <div class="annotation"> 1477 1478 <div class="pilwrap "> 1479 <a class="pilcrow" href="#section-83">¶</a> 1480 </div> 1481 <p>Is the given value a regular expression?</p> 1482 1483 </div> 1484 1485 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isRegExp</span></span> = (obj) -> !!(obj <span class="keyword">and</span> obj.exec <span class="keyword">and</span> (obj.ignoreCase <span class="keyword">or</span> obj.ignoreCase <span class="keyword">is</span> <span class="literal">false</span>))</pre></div></div> 1486 1487 </li> 1488 1489 1490 <li id="section-84"> 1491 <div class="annotation"> 1492 1493 <div class="pilwrap "> 1494 <a class="pilcrow" href="#section-84">¶</a> 1495 </div> 1496 <p>Is the given value NaN -- this one is interesting. <code>NaN != NaN</code>, and 1497<code>isNaN(undefined) == true</code>, so we make sure it's a number first.</p> 1498 1499 </div> 1500 1501 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isNaN</span></span> = (obj) -> _.isNumber(obj) <span class="keyword">and</span> window.isNaN(obj)</pre></div></div> 1502 1503 </li> 1504 1505 1506 <li id="section-85"> 1507 <div class="annotation"> 1508 1509 <div class="pilwrap "> 1510 <a class="pilcrow" href="#section-85">¶</a> 1511 </div> 1512 <p>Is a given value equal to null?</p> 1513 1514 </div> 1515 1516 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isNull</span></span> = (obj) -> obj <span class="keyword">is</span> <span class="literal">null</span></pre></div></div> 1517 1518 </li> 1519 1520 1521 <li id="section-86"> 1522 <div class="annotation"> 1523 1524 <div class="pilwrap "> 1525 <a class="pilcrow" href="#section-86">¶</a> 1526 </div> 1527 <p>Is a given variable undefined?</p> 1528 1529 </div> 1530 1531 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">isUndefined</span></span> = (obj) -> <span class="keyword">typeof</span> obj <span class="keyword">is</span> <span class="string">'undefined'</span></pre></div></div> 1532 1533 </li> 1534 1535 1536 <li id="section-87"> 1537 <div class="annotation"> 1538 1539 <div class="pilwrap for-h2"> 1540 <a class="pilcrow" href="#section-87">¶</a> 1541 </div> 1542 <h2>Utility Functions</h2> 1543 1544 </div> 1545 1546 </li> 1547 1548 1549 <li id="section-88"> 1550 <div class="annotation"> 1551 1552 <div class="pilwrap "> 1553 <a class="pilcrow" href="#section-88">¶</a> 1554 </div> 1555 <p>Run Underscore.js in noConflict mode, returning the <code>_</code> variable to its 1556previous owner. Returns a reference to the Underscore object.</p> 1557 1558 </div> 1559 1560 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">noConflict</span></span> = -> 1561 root._ = previousUnderscore 1562 <span class="keyword">this</span></pre></div></div> 1563 1564 </li> 1565 1566 1567 <li id="section-89"> 1568 <div class="annotation"> 1569 1570 <div class="pilwrap "> 1571 <a class="pilcrow" href="#section-89">¶</a> 1572 </div> 1573 <p>Keep the identity function around for default iterators.</p> 1574 1575 </div> 1576 1577 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">identity</span></span> = (value) -> value</pre></div></div> 1578 1579 </li> 1580 1581 1582 <li id="section-90"> 1583 <div class="annotation"> 1584 1585 <div class="pilwrap "> 1586 <a class="pilcrow" href="#section-90">¶</a> 1587 </div> 1588 <p>Run a function <code>n</code> times.</p> 1589 1590 </div> 1591 1592 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">times</span></span> = (n, iterator, context) -> 1593 iterator.call context, i <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="number">0.</span>..n]</pre></div></div> 1594 1595 </li> 1596 1597 1598 <li id="section-91"> 1599 <div class="annotation"> 1600 1601 <div class="pilwrap "> 1602 <a class="pilcrow" href="#section-91">¶</a> 1603 </div> 1604 <p>Break out of the middle of an iteration.</p> 1605 1606 </div> 1607 1608 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">breakLoop</span></span> = -> <span class="keyword">throw</span> breaker</pre></div></div> 1609 1610 </li> 1611 1612 1613 <li id="section-92"> 1614 <div class="annotation"> 1615 1616 <div class="pilwrap "> 1617 <a class="pilcrow" href="#section-92">¶</a> 1618 </div> 1619 <p>Add your own custom functions to the Underscore object, ensuring that 1620they're correctly added to the OOP wrapper as well.</p> 1621 1622 </div> 1623 1624 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">mixin</span></span> = (obj) -> 1625 <span class="keyword">for</span> name <span class="keyword">in</span> _.functions(obj) 1626 addToWrapper name, _[name] = obj[name]</pre></div></div> 1627 1628 </li> 1629 1630 1631 <li id="section-93"> 1632 <div class="annotation"> 1633 1634 <div class="pilwrap "> 1635 <a class="pilcrow" href="#section-93">¶</a> 1636 </div> 1637 <p>Generate a unique integer id (unique within the entire client session). 1638Useful for temporary DOM ids.</p> 1639 1640 </div> 1641 1642 <div class="content"><div class='highlight'><pre>idCounter = <span class="number">0</span> 1643_.<span class="function"><span class="title">uniqueId</span></span> = (prefix) -> 1644 (prefix <span class="keyword">or</span> <span class="string">''</span>) + idCounter++</pre></div></div> 1645 1646 </li> 1647 1648 1649 <li id="section-94"> 1650 <div class="annotation"> 1651 1652 <div class="pilwrap "> 1653 <a class="pilcrow" href="#section-94">¶</a> 1654 </div> 1655 <p>By default, Underscore uses <strong>ERB</strong>-style template delimiters, change the 1656following template settings to use alternative delimiters.</p> 1657 1658 </div> 1659 1660 <div class="content"><div class='highlight'><pre>_.templateSettings = { 1661 start: <span class="string">'<%'</span> 1662 end: <span class="string">'%>'</span> 1663 interpolate: <span class="regexp">/<%=(.+?)%>/g</span> 1664}</pre></div></div> 1665 1666 </li> 1667 1668 1669 <li id="section-95"> 1670 <div class="annotation"> 1671 1672 <div class="pilwrap "> 1673 <a class="pilcrow" href="#section-95">¶</a> 1674 </div> 1675 <p>JavaScript templating a-la <strong>ERB</strong>, pilfered from John Resig's 1676<em>Secrets of the JavaScript Ninja</em>, page 83. 1677Single-quote fix from Rick Strahl. 1678With alterations for arbitrary delimiters, and to preserve whitespace.</p> 1679 1680 </div> 1681 1682 <div class="content"><div class='highlight'><pre>_.<span class="function"><span class="title">template</span></span> = (str, data) -> 1683 c = _.templateSettings 1684 endMatch = <span class="keyword">new</span> RegExp(<span class="string">"'(?=[^"</span>+c.end.substr(<span class="number">0</span>, <span class="number">1</span>)+<span class="string">"]*"</span>+escapeRegExp(c.end)+<span class="string">")"</span>,<span class="string">"g"</span>) 1685 fn = <span class="keyword">new</span> Function <span class="string">'obj'</span>, 1686 <span class="string">'var p=[],print=function(){p.push.apply(p,arguments);};'</span> + 1687 <span class="string">'with(obj||{}){p.push(\''</span> + 1688 str.replace(<span class="regexp">/\r/g</span>, <span class="string">'\\r'</span>) 1689 .replace(<span class="regexp">/\n/g</span>, <span class="string">'\\n'</span>) 1690 .replace(<span class="regexp">/\t/g</span>, <span class="string">'\\t'</span>) 1691 .replace(endMatch,<span class="string">"✄"</span>) 1692 .split(<span class="string">"'"</span>).join(<span class="string">"\\'"</span>) 1693 .split(<span class="string">"✄"</span>).join(<span class="string">"'"</span>) 1694 .replace(c.interpolate, <span class="string">"',$1,'"</span>) 1695 .split(c.start).join(<span class="string">"');"</span>) 1696 .split(c.end).join(<span class="string">"p.push('"</span>) + 1697 <span class="string">"');}return p.join('');"</span> 1698 <span class="keyword">if</span> data <span class="keyword">then</span> fn(data) <span class="keyword">else</span> fn</pre></div></div> 1699 1700 </li> 1701 1702 1703 <li id="section-96"> 1704 <div class="annotation"> 1705 1706 <div class="pilwrap for-h2"> 1707 <a class="pilcrow" href="#section-96">¶</a> 1708 </div> 1709 <h2>Aliases</h2> 1710 1711 </div> 1712 1713 </li> 1714 1715 1716 <li id="section-97"> 1717 <div class="annotation"> 1718 1719 <div class="pilwrap "> 1720 <a class="pilcrow" href="#section-97">¶</a> 1721 </div> 1722 1723 </div> 1724 1725 <div class="content"><div class='highlight'><pre>_.forEach = _.each 1726_.foldl = _.inject = _.reduce 1727_.foldr = _.reduceRight 1728_.select = _.filter 1729_.all = _.every 1730_.any = _.some 1731_.contains = _.include 1732_.head = _.first 1733_.tail = _.rest 1734_.methods = _.functions</pre></div></div> 1735 1736 </li> 1737 1738 1739 <li id="section-98"> 1740 <div class="annotation"> 1741 1742 <div class="pilwrap for-h2"> 1743 <a class="pilcrow" href="#section-98">¶</a> 1744 </div> 1745 <h2>Setup the OOP Wrapper</h2> 1746 1747 </div> 1748 1749 </li> 1750 1751 1752 <li id="section-99"> 1753 <div class="annotation"> 1754 1755 <div class="pilwrap "> 1756 <a class="pilcrow" href="#section-99">¶</a> 1757 </div> 1758 <p>If Underscore is called as a function, it returns a wrapped object that 1759can be used OO-style. This wrapper holds altered versions of all the 1760underscore functions. Wrapped objects may be chained.</p> 1761 1762 </div> 1763 1764 <div class="content"><div class='highlight'><pre><span class="function"><span class="title">wrapper</span></span> = (obj) -> 1765 <span class="keyword">this</span>._wrapped = obj 1766 <span class="keyword">this</span></pre></div></div> 1767 1768 </li> 1769 1770 1771 <li id="section-100"> 1772 <div class="annotation"> 1773 1774 <div class="pilwrap "> 1775 <a class="pilcrow" href="#section-100">¶</a> 1776 </div> 1777 <p>Helper function to continue chaining intermediate results.</p> 1778 1779 </div> 1780 1781 <div class="content"><div class='highlight'><pre><span class="function"><span class="title">result</span></span> = (obj, chain) -> 1782 <span class="keyword">if</span> chain <span class="keyword">then</span> _(obj).chain() <span class="keyword">else</span> obj</pre></div></div> 1783 1784 </li> 1785 1786 1787 <li id="section-101"> 1788 <div class="annotation"> 1789 1790 <div class="pilwrap "> 1791 <a class="pilcrow" href="#section-101">¶</a> 1792 </div> 1793 <p>A method to easily add functions to the OOP wrapper.</p> 1794 1795 </div> 1796 1797 <div class="content"><div class='highlight'><pre><span class="function"><span class="title">addToWrapper</span></span> = (name, func) -> 1798 wrapper.prototype[name] = -> 1799 args = _.toArray arguments 1800 unshift.call args, <span class="keyword">this</span>._wrapped 1801 result func.apply(_, args), <span class="keyword">this</span>._chain</pre></div></div> 1802 1803 </li> 1804 1805 1806 <li id="section-102"> 1807 <div class="annotation"> 1808 1809 <div class="pilwrap "> 1810 <a class="pilcrow" href="#section-102">¶</a> 1811 </div> 1812 <p>Add all ofthe Underscore functions to the wrapper object.</p> 1813 1814 </div> 1815 1816 <div class="content"><div class='highlight'><pre>_.mixin _</pre></div></div> 1817 1818 </li> 1819 1820 1821 <li id="section-103"> 1822 <div class="annotation"> 1823 1824 <div class="pilwrap "> 1825 <a class="pilcrow" href="#section-103">¶</a> 1826 </div> 1827 <p>Add all mutator Array functions to the wrapper.</p> 1828 1829 </div> 1830 1831 <div class="content"><div class='highlight'><pre>_.each [<span class="string">'pop'</span>, <span class="string">'push'</span>, <span class="string">'reverse'</span>, <span class="string">'shift'</span>, <span class="string">'sort'</span>, <span class="string">'splice'</span>, <span class="string">'unshift'</span>], (name) -> 1832 method = Array.prototype[name] 1833 wrapper.prototype[name] = -> 1834 method.apply(<span class="keyword">this</span>._wrapped, arguments) 1835 result(<span class="keyword">this</span>._wrapped, <span class="keyword">this</span>._chain)</pre></div></div> 1836 1837 </li> 1838 1839 1840 <li id="section-104"> 1841 <div class="annotation"> 1842 1843 <div class="pilwrap "> 1844 <a class="pilcrow" href="#section-104">¶</a> 1845 </div> 1846 <p>Add all accessor Array functions to the wrapper.</p> 1847 1848 </div> 1849 1850 <div class="content"><div class='highlight'><pre>_.each [<span class="string">'concat'</span>, <span class="string">'join'</span>, <span class="string">'slice'</span>], (name) -> 1851 method = Array.prototype[name] 1852 wrapper.prototype[name] = -> 1853 result(method.apply(<span class="keyword">this</span>._wrapped, arguments), <span class="keyword">this</span>._chain)</pre></div></div> 1854 1855 </li> 1856 1857 1858 <li id="section-105"> 1859 <div class="annotation"> 1860 1861 <div class="pilwrap "> 1862 <a class="pilcrow" href="#section-105">¶</a> 1863 </div> 1864 <p>Start chaining a wrapped Underscore object.</p> 1865 1866 </div> 1867 1868 <div class="content"><div class='highlight'><pre>wrapper::<span class="function"><span class="title">chain</span></span> = -> 1869 <span class="keyword">this</span>._chain = <span class="literal">true</span> 1870 <span class="keyword">this</span></pre></div></div> 1871 1872 </li> 1873 1874 1875 <li id="section-106"> 1876 <div class="annotation"> 1877 1878 <div class="pilwrap "> 1879 <a class="pilcrow" href="#section-106">¶</a> 1880 </div> 1881 <p>Extracts the result from a wrapped and chained object.</p> 1882 1883 </div> 1884 1885 <div class="content"><div class='highlight'><pre>wrapper::<span class="function"><span class="title">value</span></span> = -> <span class="keyword">this</span>._wrapped</pre></div></div> 1886 1887 </li> 1888 1889 </ul> 1890 </div> 1891</body> 1892</html>