ПОЧТИ РЕШЕНО
Почти удалось заставить это работать.
Решение не дало того, что объекты Host иногда неотличимы от объектов Native. Приведенный ниже код дает сбой при тестировании isNative(window.alert)
в Chrome, поскольку движок webkit определяет функцию alert
, которая (пока) выглядит идентичной нативной.
Он использует простой javascript согласно ES3 и основан на тестировании того, что объект является нативным (в отличие от объекта Host). Однако в соответствии с определением ES3 хост-объектов: 'Любой объект, который не является нативным, является хост-объектом.' эта функция может использоваться для обнаружения хост-объектов.
// 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');
Вот список тестов JsFiddle , который можно использовать для проверки этого в IE / Firefox / Chrome.
Я не тестировал небраузерные среды, так как это немного сложнее, но поскольку код настолько прост, я не думаю, что у него возникнут какие-либо проблемы.
// ASSERT HELPER FUNCTION
var n = 0;
function assert(condition, message) {
n++;
if (condition !== true) {
document.write(n + '. FAILS: ' + (message || '(no message)') + '<br/>');
} else {
document.write(n + '. PASS: ' + (message || '(no message)') + '<br/>');
}
}
// 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');