Is there an environment-agnostic way to detect Javascript Host Objects?

前端 未结 5 1739
既然无缘
既然无缘 2020-12-31 15:31

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

5条回答
  •  礼貌的吻别
    2020-12-31 16:03

    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');​

提交回复
热议问题