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

前端 未结 5 1741
既然无缘
既然无缘 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:22

    ALMOST SOLVED

    Almost managed to get this to work.

    The solution falls short in that Host objects are sometimes undistinguishable from Native ones. The code below fails when testing isNative(window.alert) on Chrome as webkit engine defines an alert function that (so far) looks identical to a native one.

    It uses plain javascript as per ES3 and is based on testing that an object is native (as opposed to Host object). However, as per ES3 definition of Host Objects: 'Any object that is not native is a host object.' this function can be used to detect host objects.

    // ISNATIVE OBJECT DETECTION
    
    function isNative(obj) {
    
        switch(typeof obj) {
            case 'number': case 'string': case 'boolean':
                // Primitive types are not native objects
                return false;
        }  
    
        // 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;
    
        return true;
    }
    
    // CHECK IF AN OBJECT IS HOST OR NATIVE
    
    if (typeof myObject === 'object' || typeof myObject === 'function')
       alert(isNative(myObject) ? 'Native Object' : 'Host Object'); 
    

    Here is a list of JsFiddle tests that can be used to test this in IE / Firefox / Chrome.

    I havent tested Non-browser environments as its a bit more of a hassle but since the code is so basic I dont think it'll have any problems.

    // 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(isNative({}), '{} -- Plain object'); assert(isNative(function() {}), 'function() {} -- Plain function'); assert(isNative([]), '[] -- Plain array'); assert(isNative(/regex/), '/regex/ - Native regex'); assert(isNative(new Date()), 'new Date() - Native date object through instantiation'); assert(isNative(new String('string')), 'new String("string") - Native string object through instantiation'); assert(isNative(new Number(1)), 'new Number(1) - Native number object through instantiation'); assert(isNative(new Boolean(true)), 'new Boolean(true) - Native boolean object through instantiation'); assert(isNative(new Array()), 'new Array() - Native array object through instantiation'); assert(isNative(new Object()), '{} -- new Object() - Native object through instantiation'); assert(isNative(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(isNative(Animal), 'Animal -- User defined type'); assert(isNative(animal), 'animal -- Instance of User defined type'); assert(isNative(Dog), 'Dog -- User defined inherited type'); assert(isNative(dog), 'dog -- Instance of User defined inherited type'); // BUILT IN OBJECTS assert(isNative(Object), 'Object -- Built in'); assert(isNative(Array), 'Array -- Built in'); assert(isNative(Date), 'Date -- Built in'); assert(isNative(Boolean), 'Boolean -- Built in'); assert(isNative(String), 'String -- Built in'); assert(isNative(Function), 'Function -- Built in'); // PRIMITIVE TYPES assert(!isNative('string'), '"string" - Primitive string'); assert(!isNative(1), '1 - Primitive number'); assert(!isNative(true), 'true - Primitive boolean'); assert(!isNative(null), 'null - Primitive null'); assert(!isNative(NaN), 'NaN - Primitive number NotANumber'); assert(!isNative(Infinity), 'Infinity - Primitive number Infinity'); assert(!isNative(undefined), 'undefined - Primitive value undefined'); // HOST OBJECTS assert(!isNative(window), 'window -- Host object'); assert(!isNative(alert), 'alert -- Host function'); // fails on chrome assert(!isNative(document), 'document -- Host object'); assert(!isNative(location), 'location -- Host object'); assert(!isNative(navigator), 'navigator -- Host object'); assert(!isNative(parent), 'parent -- Host object'); assert(!isNative(frames), 'frames -- Host object');

提交回复
热议问题