Comparing version 0.0.3 to 0.0.4
510
lib/isA.js
/** | ||
* Copyright 2013 Gabriel Harrison | ||
* The MIT License | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy | ||
* of the License at | ||
* Copyright (c) 2013 Gabriel Harrison | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* Permission is hereby granted, free of charge, to any person obtaining | ||
* a copy of this software and associated documentation files (the "Software"), | ||
* to deal in the Software without restriction, including without limitation | ||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
* and/or sell copies of the Software, and to permit persons to whom the | ||
* Software is furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included | ||
* in all copies or substantial portions of the Software. | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
* | ||
* isA.js | ||
@@ -39,265 +47,275 @@ * | ||
* @author Gabriel Harrison (nyteshade AT gmail.com) | ||
* @version 1.0 | ||
* @version 0.0.4 | ||
*/ | ||
var hasExports = typeof(exports) != 'undefined', | ||
namespace = hasExports ? exports : | ||
(typeof (window) != 'undefined') ? window : | ||
(typeof (global) != 'undefined') ? global : null; | ||
(function() { | ||
"use strict"; | ||
if (!namespace) { | ||
console.error('Cannot locate place to export library to!'); | ||
throw new Error('Missing namespace!'); | ||
} | ||
var hasExports = typeof(exports) != 'undefined', | ||
namespace = hasExports ? exports : | ||
(typeof (window) != 'undefined') ? window : | ||
(typeof (global) != 'undefined') ? global : null; | ||
var library = (function(exports) { | ||
/** | ||
* Declare an array of Strings reported by the JavaScript VM to be the | ||
* actual toString() representation of a particular base type such that | ||
* it can be repeatedly compared with accuracy using the functions below. | ||
* | ||
* By not hardcoding the Strings here, we can guarantee that we are seeing | ||
* unique types. | ||
*/ | ||
exports.IS_A = { | ||
UNDEFINED: Object.prototype.toString.call(undefined), | ||
FUNCTION: Object.prototype.toString.call(Function()), | ||
BOOLEAN: Object.prototype.toString.call(Boolean()), | ||
OBJECT: Object.prototype.toString.call(Object()), | ||
REGEXP: Object.prototype.toString.call(RegExp()), | ||
STRING: Object.prototype.toString.call(String()), | ||
NUMBER: Object.prototype.toString.call(Number()), | ||
ARRAY: Object.prototype.toString.call(Array()), | ||
ERROR: Object.prototype.toString.call(Error()), | ||
NULL: Object.prototype.toString.call(null) | ||
}; | ||
if (!namespace) { | ||
console.error('Cannot locate place to export library to!'); | ||
throw new Error('Missing namespace!'); | ||
} | ||
/* This back reference array allows us to quickly map existing constructors | ||
* for base types to their appropriate strings without having to create new | ||
* instances of the type for comparison. */ | ||
var backRef = exports.IS_A_BACKREF = [ | ||
undefined, exports.IS_A.UNDEFINED, | ||
Function, exports.IS_A.FUNCTION, | ||
Boolean, exports.IS_A.BOOLEAN, | ||
Object, exports.IS_A.OBJECT, | ||
RegExp, exports.IS_A.REGEXP, | ||
String, exports.IS_A.STRING, | ||
Number, exports.IS_A.NUMBER, | ||
Array, exports.IS_A.ARRAY, | ||
Error, exports.IS_A.ERROR, | ||
null, exports.IS_A.NULL | ||
]; | ||
var library = (function(exports) { | ||
/** | ||
* Declare an array of Strings reported by the JavaScript VM to be the | ||
* actual toString() representation of a particular base type such that | ||
* it can be repeatedly compared with accuracy using the functions below. | ||
* | ||
* By not hardcoding the Strings here, we can guarantee that we are seeing | ||
* unique types. | ||
*/ | ||
exports.IS_A = { | ||
UNDEFINED: Object.prototype.toString.call(undefined), | ||
FUNCTION: Object.prototype.toString.call(new Function()), | ||
BOOLEAN: Object.prototype.toString.call(true), | ||
OBJECT: Object.prototype.toString.call({}), | ||
REGEXP: Object.prototype.toString.call(new RegExp()), | ||
STRING: Object.prototype.toString.call(""), | ||
NUMBER: Object.prototype.toString.call(1), | ||
ARRAY: Object.prototype.toString.call([]), | ||
ERROR: Object.prototype.toString.call(new Error()), | ||
NULL: Object.prototype.toString.call(null) | ||
}; | ||
if (!backRef.indexOf) { | ||
backRef.indexOf = function(obj) { | ||
for (var i = 0; i < backRef.length; i++) { | ||
if (backRef[i] === obj) { | ||
return i; | ||
/* This back reference array allows us to quickly map existing constructors | ||
* for base types to their appropriate strings without having to create new | ||
* instances of the type for comparison. */ | ||
var backRef = exports.IS_A_BACKREF = [ | ||
undefined, exports.IS_A.UNDEFINED, | ||
Function, exports.IS_A.FUNCTION, | ||
Boolean, exports.IS_A.BOOLEAN, | ||
Object, exports.IS_A.OBJECT, | ||
RegExp, exports.IS_A.REGEXP, | ||
String, exports.IS_A.STRING, | ||
Number, exports.IS_A.NUMBER, | ||
Array, exports.IS_A.ARRAY, | ||
Error, exports.IS_A.ERROR, | ||
null, exports.IS_A.NULL | ||
]; | ||
if (!backRef.indexOf) { | ||
backRef.indexOf = function(obj) { | ||
for (var i = 0; i < backRef.length; i++) { | ||
if (backRef[i] === obj) { | ||
return i; | ||
} | ||
} | ||
} | ||
return -1; | ||
return -1; | ||
}; | ||
} | ||
/** Quick reference function to get correct offset of backRef */ | ||
backRef.matchingType = function(baseConstructor) { | ||
var pos = this.indexOf(baseConstructor); | ||
if (pos === -1) { return Object.prototype.toString.call(baseConstructor); } | ||
return this[pos + 1]; | ||
}; | ||
} | ||
/** Quick reference function to get correct offset of backRef */ | ||
backRef.matchingType = function(baseConstructor) { | ||
var pos = this.indexOf(baseConstructor); | ||
if (pos === -1) { return Object.prototype.toString.call(baseConstructor); } | ||
return this[pos + 1]; | ||
}; | ||
/* Quick test to guarantee we have no repeated types and provide a way to | ||
* measure the accuracy of our comparison "constants" */ | ||
var _t, _t2, _count = 0, _unique = 0, _questionable = []; | ||
for (_t in exports.IS_A) { | ||
if (exports.IS_A.hasOwnProperty(_t)) { | ||
var unique = true; | ||
for (_t2 in exports.IS_A) { | ||
if (exports.IS_A.hasOwnProperty(_t)) { | ||
if (_t === _t2) { continue; } | ||
unique = exports.IS_A[_t] !== exports.IS_A[_t2]; | ||
if (!unique) { | ||
_questionable.push([_t, _t2]); | ||
break; | ||
/* Quick test to guarantee we have no repeated types and provide a way to | ||
* measure the accuracy of our comparison "constants" */ | ||
var _t, _t2, _count = 0, _unique = 0, _questionable = []; | ||
for (_t in exports.IS_A) { | ||
if (exports.IS_A.hasOwnProperty(_t)) { | ||
var unique = true; | ||
for (_t2 in exports.IS_A) { | ||
if (exports.IS_A.hasOwnProperty(_t2)) { | ||
if (_t === _t2) { continue; } | ||
unique = exports.IS_A[_t] !== exports.IS_A[_t2]; | ||
if (!unique) { | ||
_questionable.push([_t, _t2]); | ||
break; | ||
} | ||
} | ||
} | ||
if (unique) { _unique++; } | ||
} | ||
if (unique) { _unique++; } | ||
_count++; | ||
} | ||
_count++; | ||
} | ||
/** | ||
* This property should reflect 1 if every type in the IS_A dictionary | ||
* reported unique values. This will quickly tell you if your assumptions | ||
* about toString() results will be accurate or not. In the case of a value | ||
* less than 1, exports.IS_A_QUESTIONABLE will contain pairs of keys that | ||
* returned the same value for your own debugging pleasure. | ||
*/ | ||
exports.IS_A_ACCURACY = _unique / _count; | ||
exports.IS_A_QUESTIONABLE = _questionable; | ||
if (exports.IS_A_ACCURACY !== 1.0) { | ||
console.warn('IS_A dictionary reported non-unique value pairs: ', | ||
exports.IS_A_QUESTIONABLE); | ||
} | ||
/** | ||
* Cross JavaScript VM method to definitively test the type that an object | ||
* reports to the JavaScript engine itself. Accuracy will decline and/or | ||
* vary if the type is not one of the types listed in exports.IS_A, above. | ||
*/ | ||
exports.isA = function(type, object) { | ||
if (arguments.length === 1) { | ||
return Object.prototype.toString.call(type) | ||
/** | ||
* This property should reflect 1 if every type in the IS_A dictionary | ||
* reported unique values. This will quickly tell you if your assumptions | ||
* about toString() results will be accurate or not. In the case of a value | ||
* less than 1, exports.IS_A_QUESTIONABLE will contain pairs of keys that | ||
* returned the same value for your own debugging pleasure. | ||
*/ | ||
exports.IS_A_ACCURACY = _unique / _count; | ||
exports.IS_A_QUESTIONABLE = _questionable; | ||
if (exports.IS_A_ACCURACY !== 1.0) { | ||
console.warn('IS_A dictionary reported non-unique value pairs: ', | ||
exports.IS_A_QUESTIONABLE); | ||
} | ||
else { | ||
var typeString = Object.prototype.toString.call(object); | ||
return typeString === type | ||
|| typeString === exports.IS_A[type] | ||
|| typeString === backRef.matchingType(type); | ||
} | ||
}; | ||
/** | ||
* Not the most efficient way to test for undefined, but follows suit with | ||
* the other methods in this suite. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is undefined, false otherwise | ||
*/ | ||
exports.isUndefined = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.UNDEFINED; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test the type that an object | ||
* reports to the JavaScript engine itself. Accuracy will decline and/or | ||
* vary if the type is not one of the types listed in exports.IS_A, above. | ||
*/ | ||
exports.isA = function(type, object) { | ||
if (arguments.length === 1) { | ||
return Object.prototype.toString.call(type) | ||
} | ||
else { | ||
var typeString = Object.prototype.toString.call(object); | ||
return typeString === type | ||
|| typeString === exports.IS_A[type] | ||
|| typeString === backRef.matchingType(type); | ||
} | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a Function. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is a function, false otherwise | ||
*/ | ||
exports.isFunction = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.FUNCTION; | ||
}; | ||
/** | ||
* Not the most efficient way to test for undefined, but follows suit with | ||
* the other methods in this suite. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is undefined, false otherwise | ||
*/ | ||
exports.isUndefined = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.UNDEFINED; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a Boolean. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is a Boolean, false otherwise | ||
*/ | ||
exports.isBoolean = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.BOOLEAN; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a Function. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is a function, false otherwise | ||
*/ | ||
exports.isFunction = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.FUNCTION; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a RegExp. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is a RegExp, false otherwise | ||
*/ | ||
exports.isObject = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.OBJECT; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a Boolean. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is a Boolean, false otherwise | ||
*/ | ||
exports.isBoolean = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.BOOLEAN; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a RegExp. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is a RegExp, false otherwise | ||
*/ | ||
exports.isRegExp = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.REGEXP; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a RegExp. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is a RegExp, false otherwise | ||
*/ | ||
exports.isObject = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.OBJECT; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a String. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is a String, false otherwise | ||
*/ | ||
exports.isString = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.STRING; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a RegExp. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is a RegExp, false otherwise | ||
*/ | ||
exports.isRegExp = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.REGEXP; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a Number. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is a Number, false otherwise | ||
*/ | ||
exports.isNumber = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.NUMBER; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a String. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is a String, false otherwise | ||
*/ | ||
exports.isString = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.STRING; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of an Array. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is an Array, false otherwise | ||
*/ | ||
exports.isArray = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.ARRAY; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of a Number. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is a Number, false otherwise | ||
*/ | ||
exports.isNumber = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.NUMBER; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of an Error. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is an Error, false otherwise | ||
*/ | ||
exports.isError = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.ERROR; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of an Array. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is an Array, false otherwise | ||
*/ | ||
exports.isArray = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.ARRAY; | ||
}; | ||
/** | ||
* Not the most efficient way to test for null, but follows suit with | ||
* the other methods in this suite. | ||
* | ||
* @param object any object to be tested | ||
* @return true if the object is null, false otherwise | ||
*/ | ||
exports.isNull = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.NULL; | ||
}; | ||
/** | ||
* Cross JavaScript VM method to definitively test whether or not an object | ||
* is an instance of an Error. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is an Error, false otherwise | ||
*/ | ||
exports.isError = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.ERROR; | ||
}; | ||
/** | ||
* Inject isA library to the supplied scope. If null or undefined are given | ||
* as the destinationScope an exception will be thrown. | ||
* | ||
* @param destinationScope the scope to dump these library functions to | ||
*/ | ||
exports.INJECT_IS_A_LIB = function(destinationScope) { | ||
if (destinationScope === null || destinationScope === undefined) { | ||
throw new Error("Cannot locate destination scope to install to."); | ||
} | ||
for (var property in exports) { | ||
if (exports.hasOwnProperty(property)) { | ||
destinationScope[property] = exports[property]; | ||
/** | ||
* Not the most efficient way to test for null, but follows suit with | ||
* the other methods in this suite. | ||
* | ||
* @param object any object to be tested | ||
* @return boolean true if the object is null, false otherwise | ||
*/ | ||
exports.isNull = function(object) { | ||
return Object.prototype.toString.call(object) === exports.IS_A.NULL; | ||
}; | ||
/** | ||
* Inject isA library to the supplied scope. If null or undefined are given | ||
* as the destinationScope an exception will be thrown. | ||
* | ||
* @param destinationScope the scope to dump these library functions to | ||
* @return object the exports object | ||
*/ | ||
exports.INJECT_IS_A_LIB = function(destinationScope) { | ||
if (destinationScope === null || destinationScope === undefined) { | ||
throw new Error("Cannot locate destination scope to install to."); | ||
} | ||
} | ||
for (var property in exports) { | ||
if (exports.hasOwnProperty(property)) { | ||
destinationScope[property] = exports[property]; | ||
} | ||
} | ||
return exports; | ||
}; | ||
return exports; | ||
}; | ||
})({}); | ||
return exports; | ||
})({}); | ||
if (hasExports && typeof module !== 'undefined') { | ||
module.exports = function(destination) { | ||
if (!destination) { | ||
return library; | ||
} | ||
else { | ||
return library.INJECT_IS_A_LIB(destination); | ||
} | ||
}; | ||
} | ||
else if (typeof window !== 'undefined') { | ||
library.INJECT_IS_A_LIB(window); | ||
} | ||
else { | ||
namespace.isA = library; | ||
} | ||
})(); | ||
if (hasExports) { | ||
module.exports = function(destination) { | ||
if (!destination) { | ||
return library; | ||
} | ||
else { | ||
return library.INJECT_IS_A_LIB(destination); | ||
} | ||
}; | ||
} | ||
else { | ||
namespace.isA = library.INJECT_IS_A_LIB(namespace); | ||
} | ||
/*jslint browser:true,indent:2,node:true*/ |
@@ -5,3 +5,3 @@ { | ||
"description": "Reusable Object.prototype.toString type checking library", | ||
"version": "0.0.3", | ||
"version": "0.0.4", | ||
"repository": { | ||
@@ -8,0 +8,0 @@ "url": "https://github.com/nyteshade/isA.git" |
@@ -6,16 +6,24 @@ <h1> | ||
<h2>License</h2> | ||
Copyright 2013 Gabriel Harrison | ||
The MIT License | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
Copyright (c) 2013 Gabriel Harrison | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
<h2>Installation</h2> | ||
@@ -22,0 +30,0 @@ |
15538
297
97