icambron/twix.js — pull request #41 by benesch (2014-07-16 17:47:40+00:00)
Title: Basic operations speedup

Cloning moments is unreasonably slow. Avoiding cloning moments whenever possible results in a massive speedup. On my machine:

**ce2a114 (before)**
```
#contains (non-moment) x 8,950 ops/sec ±1.73% (93 runs sampled)
#contains (moment) x 9,478 ops/sec ±0.57% (91 runs sampled)
#length x 10,162 ops/sec ±0.27% (86 runs sampled)
#count x 9,642 ops/sec ±0.45% (94 runs sampled)
#countInner x 3,261 ops/sec ±0.67% (93 runs sampled)
#isEmpty x 13,005 ops/sec ±0.29% (98 runs sampled)
#isValid x 12,999 ops/sec ±0.33% (89 runs sampled)
```

**59863ae (after)**
```
#contains (non-moment) x 36,385 ops/sec ±1.02% (98 runs sampled) 4x
#contains (moment) x 1,186,753 ops/sec ±0.46% (90 runs sampled) 125x
#length x 35,423 ops/sec ±0.97% (91 runs sampled) 3.5x
#count x 9,938 ops/sec ±0.41% (87 runs sampled) 0x
#countInner x 3,352 ops/sec ±1.49% (95 runs sampled) 0x
#isEmpty x 5,175,601 ops/sec ±0.57% (97 runs sampled) 400x
#isValid x 3,119,548 ops/sec ±0.43% (93 runs sampled) 240x
```

Without these optimizations, attempting to use basic checks like `range.contains(aMoment)` within an Angular watch expression is unusably slow.

The one caveat here is that mutations to `range.start` and `range.end` will no longer be reflected in `range.contains()`, `range.engulfs()`, etc. I wasn't sure if `range.start` and `range.end` were part of the public API—they're absent from the documentation—so I went with the simplest possible solution.