291 lines
8.6 KiB
JavaScript
291 lines
8.6 KiB
JavaScript
/** section: Language
|
|
* class Object
|
|
*
|
|
* Extensions to the built-in `Object` object.
|
|
*
|
|
* Because it is dangerous and invasive to augment `Object.prototype` (i.e.,
|
|
* add instance methods to objects), all these methods are static methods that
|
|
* take an `Object` as their first parameter.
|
|
*
|
|
**/
|
|
(function() {
|
|
|
|
var _toString = Object.prototype.toString;
|
|
|
|
/**
|
|
* Object.extend(destination, source) -> Object
|
|
* - destination (Object): The object to receive the new properties.
|
|
* - source (Object): The object whose properties will be duplicated.
|
|
*
|
|
* Copies all properties from the source to the destination object. Returns
|
|
* the destination object.
|
|
**/
|
|
function extend(destination, source) {
|
|
for (var property in source)
|
|
destination[property] = source[property];
|
|
return destination;
|
|
}
|
|
|
|
/**
|
|
* Object.inspect(object) -> String
|
|
* - object (Object): The item to be inspected.
|
|
*
|
|
* Returns the debug-oriented string representation of the object.
|
|
*
|
|
* `undefined` and `null` are represented as such.
|
|
*
|
|
* Other types are checked for a `inspect` method. If there is one, it is
|
|
* used; otherwise, it reverts to the `toString` method.
|
|
*
|
|
* Prototype provides `inspect` methods for many types, both built-in and
|
|
* library-defined — among them `String`, `Array`, `Enumerable` and `Hash`.
|
|
* These attempt to provide useful string representations (from a
|
|
* developer's standpoint) for their respective types.
|
|
**/
|
|
function inspect(object) {
|
|
try {
|
|
if (isUndefined(object)) return 'undefined';
|
|
if (object === null) return 'null';
|
|
return object.inspect ? object.inspect() : String(object);
|
|
} catch (e) {
|
|
if (e instanceof RangeError) return '...';
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Object.toJSON(object) -> String
|
|
* - object (Object): The object to be serialized.
|
|
*
|
|
* Returns a JSON string.
|
|
*
|
|
* `undefined` and `function` types have no JSON representation. `boolean`
|
|
* and `null` are coerced to strings.
|
|
*
|
|
* For other types, `Object.toJSON` looks for a `toJSON` method on `object`.
|
|
* If there is one, it is used; otherwise the object is treated like a
|
|
* generic `Object`.
|
|
**/
|
|
function toJSON(object) {
|
|
var type = typeof object;
|
|
switch (type) {
|
|
case 'undefined':
|
|
case 'function':
|
|
case 'unknown': return;
|
|
case 'boolean': return object.toString();
|
|
}
|
|
|
|
if (object === null) return 'null';
|
|
if (object.toJSON) return object.toJSON();
|
|
if (isElement(object)) return;
|
|
|
|
var results = [];
|
|
for (var property in object) {
|
|
var value = toJSON(object[property]);
|
|
if (!isUndefined(value))
|
|
results.push(property.toJSON() + ': ' + value);
|
|
}
|
|
|
|
return '{' + results.join(', ') + '}';
|
|
}
|
|
|
|
/**
|
|
* Object.toQueryString(object) -> String
|
|
* object (Object): The object whose property/value pairs will be converted.
|
|
*
|
|
* Turns an object into its URL-encoded query string representation.
|
|
*
|
|
* This is a form of serialization, and is mostly useful to provide complex
|
|
* parameter sets for stuff such as objects in the Ajax namespace (e.g.
|
|
* [[Ajax.Request]]).
|
|
*
|
|
* Undefined-value pairs will be serialized as if empty-valued. Array-valued
|
|
* pairs will get serialized with one name/value pair per array element. All
|
|
* values get URI-encoded using JavaScript's native `encodeURIComponent`
|
|
* function.
|
|
*
|
|
* The order of pairs in the serialized form is not guaranteed (and mostly
|
|
* irrelevant anyway) — except for array-based parts, which are serialized
|
|
* in array order.
|
|
**/
|
|
function toQueryString(object) {
|
|
return $H(object).toQueryString();
|
|
}
|
|
|
|
/**
|
|
* Object.toHTML(object) -> String
|
|
* - object (Object): The object to convert to HTML.
|
|
*
|
|
* Converts the object to its HTML representation.
|
|
*
|
|
* Returns the return value of `object`'s `toHTML` method if it exists; else
|
|
* runs `object` through [[String.interpret]].
|
|
**/
|
|
function toHTML(object) {
|
|
return object && object.toHTML ? object.toHTML() : String.interpret(object);
|
|
}
|
|
|
|
/**
|
|
* Object.keys(object) -> Array
|
|
* - object (Object): The object to pull keys from.
|
|
*
|
|
* Returns an array of the object's property names.
|
|
*
|
|
* Note that the order of the resulting array is browser-dependent — it
|
|
* relies on the `for…in` loop, for which the ECMAScript spec does not
|
|
* prescribe an enumeration order. Sort the resulting array if you wish to
|
|
* normalize the order of the object keys.
|
|
**/
|
|
function keys(object) {
|
|
var results = [];
|
|
for (var property in object)
|
|
results.push(property);
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Object.values(object) -> Array
|
|
* - object (Object): The object to pull values from.
|
|
*
|
|
* Returns an array of the object's values.
|
|
*
|
|
* Note that the order of the resulting array is browser-dependent — it
|
|
* relies on the `for…in` loop, for which the ECMAScript spec does not
|
|
* prescribe an enumeration order.
|
|
*
|
|
* Also, remember that while property _names_ are unique, property _values_
|
|
* have no such constraint.
|
|
**/
|
|
function values(object) {
|
|
var results = [];
|
|
for (var property in object)
|
|
results.push(object[property]);
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Object.clone(object) -> Object
|
|
* - object (Object): The object to clone.
|
|
*
|
|
* Creates and returns a shallow duplicate of the passed object by copying
|
|
* all of the original's key/value pairs onto an empty object.
|
|
*
|
|
* Do note that this is a _shallow_ copy, not a _deep_ copy. Nested objects
|
|
* will retain their references.
|
|
*
|
|
* <h5>Examples</h5>
|
|
*
|
|
* var original = {name: 'primaryColors', values: ['red', 'green', 'blue']};
|
|
* var copy = Object.clone(original);
|
|
* original.name;
|
|
* // -> "primaryColors"
|
|
* original.values[0];
|
|
* // -> "red"
|
|
* copy.name;
|
|
* // -> "primaryColors"
|
|
* copy.name = "secondaryColors";
|
|
* original.name;
|
|
* // -> "primaryColors"
|
|
* copy.name;
|
|
* // -> "secondaryColors"
|
|
* copy.values[0] = 'magenta';
|
|
* copy.values[1] = 'cyan';
|
|
* copy.values[2] = 'yellow';
|
|
* original.values[0];
|
|
* // -> "magenta" (it was a shallow copy, so they shared the array)
|
|
**/
|
|
function clone(object) {
|
|
return extend({ }, object);
|
|
}
|
|
|
|
/**
|
|
* Object.isElement(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is a DOM node of type 1; `false` otherwise.
|
|
**/
|
|
function isElement(object) {
|
|
return !!(object && object.nodeType == 1);
|
|
}
|
|
|
|
/**
|
|
* Object.isArray(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is an array; false otherwise.
|
|
**/
|
|
function isArray(object) {
|
|
return _toString.call(object) == "[object Array]";
|
|
}
|
|
|
|
|
|
/**
|
|
* Object.isHash(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is an instance of the [[Hash]] class; `false`
|
|
* otherwise.
|
|
**/
|
|
function isHash(object) {
|
|
return object instanceof Hash;
|
|
}
|
|
|
|
/**
|
|
* Object.isFunction(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is of type `function`; `false` otherwise.
|
|
**/
|
|
function isFunction(object) {
|
|
return typeof object === "function";
|
|
}
|
|
|
|
/**
|
|
* Object.isString(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is of type `string`; `false` otherwise.
|
|
**/
|
|
function isString(object) {
|
|
return _toString.call(object) == "[object String]";
|
|
}
|
|
|
|
/**
|
|
* Object.isNumber(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is of type `number`; `false` otherwise.
|
|
**/
|
|
function isNumber(object) {
|
|
return _toString.call(object) == "[object Number]";
|
|
}
|
|
|
|
/**
|
|
* Object.isUndefined(object) -> Boolean
|
|
* - object (Object): The object to test.
|
|
*
|
|
* Returns `true` if `object` is of type `string`; `false` otherwise.
|
|
**/
|
|
function isUndefined(object) {
|
|
return typeof object === "undefined";
|
|
}
|
|
|
|
extend(Object, {
|
|
extend: extend,
|
|
inspect: inspect,
|
|
toJSON: toJSON,
|
|
toQueryString: toQueryString,
|
|
toHTML: toHTML,
|
|
keys: keys,
|
|
values: values,
|
|
clone: clone,
|
|
isElement: isElement,
|
|
isArray: isArray,
|
|
isHash: isHash,
|
|
isFunction: isFunction,
|
|
isString: isString,
|
|
isNumber: isNumber,
|
|
isUndefined: isUndefined
|
|
});
|
|
})();
|