I\'m writing a Javascript stacktrace library. The library needs to detect wether a particular object or function was created by the programmer or was there as part of the en
Here's a newer version of isNative
that rejects all objects with a native implementation for toString
, which solves the problem for the stack trace library but doesn't answer the question posted here satisfactorily. Where this approach fails for the latter is it filters out all built-in type definitions such as Object
, Date
, String
, Math
, etc., which are not host objects themselves. Also, this solution is dependent on how the environment outputs native/built-in function definitions (it must include "[native code]" for the function to work). Since the behaviour of the function is different, it's been renamed isUserObject
.
// USER OBJECT DETECTION
function isUserObject(obj) {
// Should be an instance of an Object
if (!(obj instanceof Object)) return false;
// Should have a constructor that is an instance of Function
if (typeof obj.constructor === 'undefined') return false;
if (!(obj.constructor instanceof Function)) return false;
// Avoid built-in functions and type definitions
if (obj instanceof Function &&
Function.prototype.toString.call(obj).indexOf('[native code]') > -1)
return false;
return true;
}
// CHECK IF AN OBJECT IS USER-CREATED OR NOT
if (typeof myObject === 'object' || typeof myObject === 'function')
alert(isUserObject(myObject) ? 'User Object' : 'Non-user Object');
Here is a list of JsFiddle tests that can be used to test this in various browsers.
// ASSERT HELPER FUNCTION
var n = 0;
function assert(condition, message) {
n++;
if (condition !== true) {
document.write(n + '. FAILS: ' + (message || '(no message)') + '
');
} else {
document.write(n + '. PASS: ' + (message || '(no message)') + '
');
}
}
// USER CREATED OBJECTS
assert(isUserObject({}), '{} -- Plain object');
assert(isUserObject(function() {}), 'function() {} -- Plain function');
assert(isUserObject([]), '[] -- Plain array');
assert(isUserObject(/regex/), '/regex/ - Native regex');
assert(isUserObject(new Date()), 'new Date() - Native date object through instantiation');
assert(isUserObject(new String('string')), 'new String("string") - Native string object through instantiation');
assert(isUserObject(new Number(1)), 'new Number(1) - Native number object through instantiation');
assert(isUserObject(new Boolean(true)), 'new Boolean(true) - Native boolean object through instantiation');
assert(isUserObject(new Array()), 'new Array() - Native array object through instantiation');
assert(isUserObject(new Object()), '{} -- new Object() - Native object through instantiation');
assert(isUserObject(new Function('alert(1)')), '{} -- Native function through instantiation');
// USER OBJECT INSTANTIATION AND INHERITANCE
var Animal = function() {};
var animal = new Animal();
var Dog = function() {};
Dog.prototype = animal;
var dog = new Dog();
assert(isUserObject(Animal), 'Animal -- User defined type');
assert(isUserObject(animal), 'animal -- Instance of User defined type');
assert(isUserObject(Dog), 'Dog -- User defined inherited type');
assert(isUserObject(dog), 'dog -- Instance of User defined inherited type');
// BUILT IN OBJECTS
assert(!isUserObject(Object), 'Object -- Built in');
assert(!isUserObject(Array), 'Array -- Built in');
assert(!isUserObject(Date), 'Date -- Built in');
assert(!isUserObject(Boolean), 'Boolean -- Built in');
assert(!isUserObject(String), 'String -- Built in');
assert(!isUserObject(Function), 'Function -- Built in');
// PRIMITIVE TYPES
assert(!isUserObject('string'), '"string" - Primitive string');
assert(!isUserObject(1), '1 - Primitive number');
assert(!isUserObject(true), 'true - Primitive boolean');
assert(!isUserObject(null), 'null - Primitive null');
assert(!isUserObject(NaN), 'NaN - Primitive number NotANumber');
assert(!isUserObject(Infinity), 'Infinity - Primitive number Infinity');
assert(!isUserObject(undefined), 'undefined - Primitive value undefined');
// HOST OBJECTS
assert(!isUserObject(window), 'window -- Host object');
assert(!isUserObject(alert), 'alert -- Host function');
assert(!isUserObject(document), 'document -- Host object');
assert(!isUserObject(location), 'location -- Host object');
assert(!isUserObject(navigator), 'navigator -- Host object');
assert(!isUserObject(parent), 'parent -- Host object');
assert(!isUserObject(frames), 'frames -- Host object');