Getting Started

Installing

Sugar builds can be downloaded, or installed with npm or bower:

npm install sugar --save

bower install sugar --save

Usage

Sugar is a library that provides utility functions for working with native objects. The Sugar global is the main point of interaction, and exposes three different ways of working with the library:

Looking for dates?

If you've picked up the basics, check out this guide to get jump starting working with dates in Sugar!

Default

By default, all Sugar methods exist on the global object as static functions. They are organized into namespaces that correspond to native classes: Sugar.Array, Sugar.Date, etc. Those marked as "instance" in the docs can be called statically as well, taking the instance as the first argument and other arguments after:

Sugar.Number.random(1, 100);
Sugar.Date.create('next Friday');
Sugar.Array.unique([1,2,2,3]);
Sugar.Date.format(new Date(), '%Y-%m-%d');

Chainables

In addition to holding static functions, Sugar namespaces are also themselves constructors. They have all instance methods, both native and Sugar, mapped to their prototype and available to them. When a chainable is created, it will wrap the object passed to it as the first argument. All methods called on the chainable object will operate on this object and return a new chainable that wraps the result, allowing methods to be chained together. When the result is needed, simply access it with the raw property:

var arr = new Sugar.Array([1,2]); arr.concat([2,3]).unique().raw;
var num = new Sugar.Number(3.1415); num.round(1).toFixed(2).raw;

Array and Date chainables have enhanced constructors that pass arguments to their create methods before wrapping them. This allows for some expressive shortcuts:

var date = new Sugar.Date('2 weeks ago'); date.raw;

The Object module also provides a number of methods designed to work well with chainables. To start, it provides the basic methods has, get, and set, which by default operate only on the object's own properties, and allow special dot and bracket syntax for accessing deep properties. This makes chainables very useful when handling complex data structures:

var obj = new Sugar.Object(data); obj.has('users').raw;
var obj = new Sugar.Object(data); obj.get('users[2].profile.hobbies').raw;
var users = new Sugar.Object(usersByName); users.merge(moreUsersByName); users.average('profile.likes').round(2).raw;

Chainables can even be used with vanilla Javascript operators, as their raw property is also exposed through the use of valueOf. Note however that doing this will also effectively unwrap the chainable:

new Sugar.Number(5) == 5
new Sugar.Number(5) >= 4
new Sugar.Number(5) * new Sugar.Number(5)
Some live examples on this site can toggle between "Default" and "Extended" modes. Chainables should be identical to "Extended" with the understanding that they must be created first.

Extended Mode

Finally, Sugar also has the ability to map its methods directly onto natives and their prototypes so that they are always available. This behavior is opt-in and controlled by the extend method:

Sugar.extend();
[1,2,2,3].unique();
(3.1415).round(1).toFixed(2);
new Date().format('%Y-%m-%d');

This method has a number of options that allow for fine-grained control of method extension:

// Extend only Array Sugar.Array.extend();
// Extend Array and Date Sugar.extend({ namespaces: [Array, Date] });
// Extend everything but Array Sugar.extend({ except: [Array] });
Sugar will not extend Object.prototype. Object methods marked in the docs as "instance" are instead mapped to the Object global and are called statically on it. However, they are still available as instance methods to chainables.

Choosing a Mode

Static functions and chainables are not technically "modes" as they can be used at any time. Chainables are often useful when working with more complex objects such as data objects, arrays, and dates, while static functions are easier for simple operations on primitives. Both can be used interchangeably.

In contast, extended mode must be activated with the extend method, which will modify built-in objects in the global scope. The ability to augment natives is very powerful, and as such comes with some caveats. First, the choice to modify the global scope is something that everyone reading your code should be aware of. If you are working on a team, clearly documenting native modifications makes it easier to anticipate and track down application bugs when they occur.

Do not use extended mode if you are developing a library or other form of middleware. This is due to both awareness of the global scope described above as well as potential conflicts with versioning if other versions of Sugar exist. Extended mode should only be used by end users.

Second, although Sugar has long advocated the safe extension of natives, it is important to note that the issue is contentious. Many developers are against the idea of native "monkey patching" entirely. Unfortunately, the reasons are very much wrapped up in the details, and any definition of "safe" depends heavily on the approach. The link above provides a detailed description of the issues here, including those that Sugar actively avoids to ultimately justify its position. If you choose to use extended mode, being aware of the consequences and potential issues is always a good idea.

npm

The sugar npm package allows methods as well as entire modules to be required individually. If you are using a build tool like Browserify, this will make it simple to create smaller custom builds without going through the download page. All packages also include pre-built distributions in the dist/ directory.

When an entry point is required (the package name or entire modules), it will return a reference to Sugar, which is equivalent to the global object in the browser. All methods will be defined on this object and can be called as normal. Requiring an individual method will define it on Sugar and additionally return a reference to its static form that can be called immediately:

// Require all modules var Sugar = require('sugar'); Sugar.Number.round(3.1415);
// Require only the Number module var Sugar = require('sugar/number'); Sugar.Number.round(3.1415);
// Require only the "round" method var round = require('sugar/number/round'); round(3.1415);

Modules are also available as separate npm packages, and are used in the same way. All Sugar npm packages define methods on the same core object, so any return value can be used.

// Require just the Array module var Sugar = require('sugar-array'); Sugar.Array.unique([1,2,2]);
// Require multiple modules var Sugar = require('sugar-array'); require('sugar-inflections'); Sugar.Array.unique([1,2,2]); Sugar.String.pluralize('boot');

As the npm package is designed with node in mind, polyfills must be explicitly required (the sugar entry point will not include them), and will immediately apply themselves if the methods they polyfill are missing.

// Require and apply ES6 polyfills require('sugar/polyfills/es6');

Summary

In summary, Sugar defines helpful utility methods that can be called as static functions on the Sugar global object, instance methods through chainables, or by directly extending natives in extended mode. All three methods can be used together, but use caution and understand the consequences of using extended mode. Custom builds can be created, either through the download page, or with npm.

More!

The full API documentation is available here. The main method API lets you quickly browse methods and bookmark them. In addition to filtering methods for easy reference, bookmarks can also be used to create a custom build. Other concepts in the documentation include: