1.4.0◀Back | Minified | Changelog | Cautionlog
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.
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% faster
Array#findAll/findIndex/map/any/count/sumup to 11,270% faster
Object.mapup to 682% faster
Array#min/max/less/moreup to 83% faster
Object.isString/isNumber/isBooleanup to 77% faster
String#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.
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 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:
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
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...
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#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
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.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:
Function#everywhich executes a function every
msmilliseconds or until canceled.
String#truncateOnWords. Part of the
String#truncatefunctionality is now here.
- Timezone formatting tokens changed to align with Moment.js better.
Object.fromQueryStringand replaced with optional boolean casting.
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
- 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
rejectreturning 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
Function#lazy, which is now false by default.
- Fixed bug with array like objects iterated over with
loop = true.
String#truncatenot returning primitives.
String#repeatis now aligned more with spec.