如何确定JavaScript函数是本机的(不测试'[native code]')

Fra*_*ger 16 javascript native function node.js

我想知道是否有办法区分JavaScript脚本函数(function(){})和JavaScript本机函数(如Math.cos).
我已经知道了这个func.toString().indexOf('[native code]') != -1技巧,但我想知道是否有另一种方法来检测它.

context:
我需要创建一个No-op转发ES6代理,它可以处理对象上的本机函数但它失败了TypeError: Illegal invocation(参见使用ES6 Proxy和node.js的非法调用错误).

为了解决这个问题,我.bind()getProxy 的处理程序中运行了所有函数,但如果我能有效地检测本机函数,我只需要.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
Run Code Online (Sandbox Code Playgroud)

编辑:
目前,最好的解决方案是测试,!('prototype' in fun)但它不适用于require('os').cpus......

Nin*_*olz 13

您可以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 
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 7

我对这个主题的总结:不要使用它,它不起作用.您无法确定函数是否为原生函数,因为它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) ));
Run Code Online (Sandbox Code Playgroud)

由于Tareq在此评论中链接的John-David Dalton版本基本上与代码不起作用相同.我检查了一下.

Nina的方法也遵循类似的原则,因为[native code]在尝试将其解析为新函数时,函数体中的部分也会抛出错误.

确定你正在处理的函数的唯一安全方法是本机函数,是保存对本机函数的引用并将你的函数与该引用进行比较,但我想这不是你的用例的选项.