Sugar provides a number of methods that make working with objects in Javascript easier. As Sugar will not modify the Object prototype by default, all methods exist directly on the Object class. However, Sugar also gives you the ability to create extended objects with hash methods available to them. Finally, you can call Object.extend() which will map all methods to Object.prototype, making them available to all Javascript objects.
It first helps to define exactly what an "object" is in Javascript, as the term itself can be a source of confusion. "object" is commonly used to mean any of the following:
An object in its most basic form is a simple key/value store, often called an "object literal". The syntax { key: 'value' } is an example of an object literal, similar to JSON, which is a string representation of an object literal. Programmers from other backgrounds may also know them as "hashes", "dictionaries", and "associative arrays". However, the Sugar docs try to avoid these terms to prevent confusion as, in the end, object literals are still simply "objects" to Javascript.
Any instance of a class in Javascript can also be considered an "object", as all instances ultimately inherit from the Object class. This includes instances of built-in data types such as Array, RegExp, and Date.
"Object" (note the capital "O") is the root class from which all other objects in Javascript inherit.
Javascript "primitives" are a potential source of confusion as certain types (strings, numbers, booleans) do inherit from the Object class, however exhibit some unique behavior as primitives. undefined and null are not objects, however null responds to typeof as if it was. The exact behavior is beyond the scope of this document, however due to the complexity and confusion, it's not uncommon to see any Javascript data type potentially being referred to (sometimes mistakenly) as an "object".
To alleviate some of the issues with determining data types of built-in and primitive objects, Sugar provides a number of type checking methods. These all follow the pattern is + type, and can be considered more reliable than typeof and instanceof, both of which are known to produce unintended results in various cases. All type methods are available directly on the Object class. Their instance method form is only available when explicitly opted-in by Object.extend(). Note that null and undefined can be checked by simply using the strict equality operator ===.
|
Method
|
Description
|
|---|---|
| isString | Returns true if the object is a string. |
| isNumber | Returns true if the object is a number |
| isBoolean | Returns true if the object is a boolean. |
| isRegExp | Returns true if the object is a regexp. |
| isFunction | Returns true if the object is a function. |
| isDate | Returns true if the object is a date. |
| isArray | Returns true if the object is an array. |
| isObject | Returns true if the object is a plain object, such as an object literal. Anything that is NOT an object literal will return false. This includes arrays, inherited classes, and null. Extended objects are also true here. |
| isNaN | Returns true if, and only if, the object is NaN. This is notably different from the global function isNaN, which means "not a number" and returns true for all data types that are not numbers. |
Sugar provides a number of methods for working with Javascript object literals (often called "hashes" in other languages). As Javascript makes no distinction between "hashes" and other objects, these methods exist as class methods directly on Object. However, they can be used as instance methods through Object.extend() or in extended objects.
|
Method
|
Description
|
|---|---|
| keys | Returns an array populated with the keys of the object. |
| values | Returns an array populated with the values of the object. |
| isEmpty | Returns true if no properties are defined in the object. |
| each | Steps through each of the properties in the object, calling a callback for each one. Returns the object. |
| equal | Tests equality between two objects, including primitives and deep objects / arrays. Note that the instance method form is equals. |
| clone | Creates a clone of the object. By default this is a shallow clone (nested objects/arrays will be copied by reference only), however passing true as the second parameter will create a deep clone. |
| merge | Merges two objects. The first 2 arguments are the objects to be merged. The third parameter is a boolean that, like Object.clone will determine whether the merge is shallow or deep. The last parameter passed to this method is used to direct how conflicts should be handled. true (the default) indicates that existing properties should always be overwritten. false indicates that existing properties should always be preserved. Finally a callback can be passed here to allow dynamic resolution of the conflict. |
| watch | Watches a given property of an object and allows a callback to be run when the property has changed. This method is useful to allow property validation. It unfortunately does not work in all browsers, notably it will not work in IE8 and below. |
As Sugar does not modify Object.prototype by default, all hash methods exist directly on the Object class. However when working with data it can be much more intuitive to have these methods available as instance methods. Extended objects in Sugar bridge this gap by providing a hash-like object with all these methods available to them.
Extended objects are created through Object.extended, which can be passed a standard object literal that will determine the initial properties. Extended objects can be used exactly like standard Javascript objects, except that they will have Hash methods available to them as instance methods. All arguments, minus passing the object itself, are identical.
The extend method exists on all built-in classes in Sugar as a way to extend natives with methods of your own. However, calling Object.extend() with no arguments will perform a special function, mapping the type methods and hash methods to Object.prototype, allowing all Javascript objects, including primitives, access to them as instance methods.
While this is powerful and can add expressiveness to your code, it is recommended to use this option with caution. First, it is discouraged if you are a plugin developer and there is any chance that your code will be run by others outside your control. Additionally, if it is causing unexpected errors, consider removing it while debugging, as conflicts on certain object properties may be to blame.
Issues that arise when using Object.extend() can nearly always be attributed to bad practice somewhere in your code (most notably iteration over objects using a for..in loop without using hasOwnProperty(), more on this here). However, Sugar acknowledges that modern web developers' code is often not their own, and tracking down other developer's errors is often too costly and time consuming. This is the main reasoning behind keeping this method as opt-in.