1.4.0
◀Back | Minified | Changelog | Cautionlog2013-08-24
This update brings a lot of changes, so please have a look at the Cautionlog above to make upgrading a lot less painful!
Also, if you are unable to upgrade, please look here for a patch that will provide better future-proofing for older versions.
Performance Enhancements
By far the biggest change in v1.4 is an across the board look at performance. Some of the more dramatic changes include:
Date#formatup to 21,400% fasterArray#findAll/findIndex/map/any/count/sumup to 11,270% fasterObject.mapup to 682% fasterArray#min/max/less/moreup to 83% fasterObject.isString/isNumber/isBooleanup to 77% fasterArray#atandString#atup to 242% faster for single index lookups.Range#everyup to 52% faster for dates, 1,500% faster for numbers/strings.String#assignup to 30% faster.
Although some methods have been given special attention, many of the refactorings were on internal utility methods, which means that the performance enhancements will have a very wide affect. To demonstrate this I looked at simple date creation, an area that on the surface hasn't changed since the last version:
This method, for this format, is now 23% faster thanks to things like speeding up internal type checking etc. Different methods for different cases should also show similar gains.
Natural Sorting
Array sorting using Array#sortBy now has an added feature to its string collation system which will perform a natural sort by default. This means that if it encounters numeric values it will sort them by their numericality instead of as a string. This means that "25" will be sorted after "7", etc. This option can be set by changing the flag Array.AlphanumericSortNatural. Additionally, the string collation function itself is now exposed globally as Array.AlphanumericSort, which means it can be passed directly into Javasript native Array#sort as well.
Ranges
Ranges were previously a concept that only existed for dates and was a dependency of the Date package. It is now moved out into its own package, simplified, and now works with numbers and strings as well! Syntax for creating a range is the same:
New to ranges is the ability to deal with inverted ranges (a higher number/date can iterate down to a lower one), and the clamp method which will contain a value to within the range:
The clamp method as well as cap (which only limits an upper number) are also now aliases on the numbers:
Additionally, the previous method duration is now renamed to span. Finally, Array.create can understand ranges and convert them to arrays when needed.
Array.find and Array.findIndex
These methods that are defined in the ES6 spec previously existed but worked slightly differently. They have now been aligned with spec and the previous functionality has been moved:
Additionally these methods will act as polyfills, so when they are implemented in later browser versions they will fall back to native implementations. Which brings us to...
Better future-proofing
Sugar previously had a very simple policy. It would never overwrite methods in the global namespace if they were there first. Although this seems to make sense on the surface, it presents a very pernicious problem: if browsers change to add a method that collides, it will effectively overwrite ("underwrite"?) the Sugar implementation. It means that a browser update initiated by the user could potentially cause a script to break.
Of course staying on top of the spec and anticipating such changes is the real name of the game (with the above changes to Array#find and Array#findIndex and a couple others, Sugar is now fully in line with the ES6 spec for the foreseeable future). However there may be many reasons that a user can't upgrade, and a browser update should not cause breakages.
For this reason, Sugar has made the reluctant decision to instead default to overriding those methods that it has not deemed polyfills (which it will fall back to, conversely). Although this unfortunately makes Sugar feel less "friendly", real world usage has shown this to be a much better solution. In the end, if a user explicitly includes the Sugar library, they need to be guaranteed that the methods they are expecting will actually be there and not suddenly change.
More natural padding
Previously String#pad, String#padLeft, and String#padRight worked in a rather counter-intuitive manner -- if 20 was passed they would put 20 characters on the ends of the string. They have now changed to be analagous to Number#pad and will add only enough padding to reach the specified length. If they string is already larger than this length, the method effectively does nothing.
More control over date creation
New to this version is Date.SugarNewDate. This hook is a way to override the Sugar internal date creation mechanism, which is now consolidated into one place. The common use case for this is timezones. The topic gets a bit complicated -- Javascript dates have no concept of timezones except the one of the current browser locale, which makes having a date in another timezone tricky. Often to get around this dates are created and then shifted to act as though they were in another timezone on the surface (even though the underlying zone is the same). While this method may work, there are many cases when Sugar creates, uses, and disposes of dates before a user can get at them to shift the zone. This often happens in date comparison date.is('the day after tomorrow'). Date.SugarNewDate serves as a hook to allow any new date created to pass through this function before being used:
Exposing this as a function gives the user maximum control, allowing even use of full timezone libraries that take into account Daylight Savings Time, etc, for maximum precision:
Other changes
- Added
Function#everywhich executes a function everymsmilliseconds or until canceled. - Added
String#truncateOnWords. Part of theString#truncatefunctionality is now here. - Timezone formatting tokens changed to align with Moment.js better.
- Added
Date#beginningOfISOWeekandDate#endOfISOWeek - Removed
deepargument fromObject.fromQueryStringand replaced with optional boolean casting. - Removed
String#normalize. Object.clonenow only works on known object types and does not work on instances of user-created classes.String#assignnow can be passed an array as well as enumerated arguments.- Fix for
isThisWeekbeing false when not"en"locale. - Fix for
Array#createnot working on argument objects of zero-length (Issue #299). - Fix for
String#capitalizecapitalizing after apostrophes (Issue #325). - Fix for extended objects
selectandrejectreturning plain objects. - Fix for
Object.mergenot merging certain deep objects. - Fix for environments where regexes are functions.
- Fix for
Function#cancelnot properly clearing all timers (Issue #346). - Fix for lazy functions not being able to recursively call themselves.
- Added option
immediatetoFunction#lazy, which is now false by default. - Fixed bug with array like objects iterated over with
loop = true. - Fixed
String#truncatenot returning primitives. String#repeatis now aligned more with spec.String#padfollows suit.