Как определить, что функция JavaScript является родной (без тестирования '[native code]')

Я хотел бы знать, есть ли способ отличить функцию JavaScript script (function(){}) от встроенной функции JavaScript (например, Math.cos).
Я уже знаю трюк func.toString().indexOf('[native code]') != -1, но мне было интересно, есть ли другой способ его обнаружить.

Контекст:
Мне нужно создать No-op forwarding ES6 Proxy, который может обрабатывать собственные функции для объекта, но с ошибкой TypeError: Illegal invocation (см. Ошибка незаконного вызова с использованием ES6 Proxy и node.js).

Чтобы обойти это я .bind() все мои функции в обработчике get моего прокси-сервера, но если бы я мог эффективно обнаруживать собственную функцию, мне нужно будет только .bind() выполнять эти собственные функции.

подробнее: https://github.com/FranckFreiburger/module-invalidate/blob/master/index.js#L106

Примечание:

(function() {}).toString() -> "function () {}"
(function() {}).prototype  -> {}

(require('os').cpus).toString() -> "function getCPUs() { [native code] }"
(require('os').cpus).prototype  -> getCPUs {}

(Math.cos).toString() -> "function cos() { [native code] }"
(Math.cos).prototype  -> undefined

(Promise.resolve().then).toString() -> "function then() { [native code] }"
(Promise.resolve().then).prototype  -> undefined

изменить
На данный момент лучшим решением является проверка !('prototype' in fun), но он не будет работать с require('os').cpus...

Ответы

Ответ 1

Вы можете try использовать Function с toString значение функции. Если он не выдает ошибку, вы получаете пользовательскую функцию, иначе у вас есть нативная функция.

function isNativeFn(fn) {
    try {
        void new Function(fn.toString());    
    } catch (e) {
        return true;
    }
    return false;
}

function customFn() { var foo; }

console.log(isNativeFn(Math.cos));          // true
console.log(isNativeFn(customFn));          // false
console.log(isNativeFn(customFn.bind({}))); // true, because bind 

Ответ 2

Мое резюме по этой теме: не используйте его, оно не работает. Вы не можете точно определить, является ли функция родной, потому что Function#bind() также создает "собственные" функции.

function isSupposedlyNative(fn){
    return (/\{\s*\[native code\]\s*\}/).test(fn);
}

function foo(){ }
var whatever = {};

console.log("Math.cos():", isSupposedlyNative( Math.cos ));
console.log("foo():", isSupposedlyNative( foo ));
console.log("foo.bind():", isSupposedlyNative( foo.bind(whatever) ));