Как определить, что функция 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) ));