如何确定 JavaScript 函数是原生的(无需测试"[原生代码]")



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

上下文:
我需要创建一个可以在对象上处理本机函数但使用TypeError: Illegal invocation失败的NO-OP转发ES6代理(请参阅使用ES6 Proxy和Node.js的非法调用错误)。

要在我的代理的get处理程序中进行.bind()解决此问题,但是如果我可以有效地检测天然功能,我只需要.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 ...

您可以使用 Function使用具有函数的toString值的CC_11构造函数。如果没有丢失错误,则会获得自定义功能,否则您有一个本机函数。

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 

我对此主题的摘要:不要使用它,它行不通。您不能肯定地检测到一个函数是本机的,因为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) ));

以及塔雷克(Tareq)在此评论中链接的约翰·戴维·道尔顿(John-David Dalton)的版本基本相同,代码也无法正常工作。我已经检查过。

和NINA的方法在类似的原理上起作用,因为它再次是功能主体中的[native code]部分,当试图将其解析为新功能时会引发错误。

确定您要处理的功能的唯一安全方法是本机函数,是保存对本机函数并将您的函数与该参考进行比较,但是我想这对您的用例没有选择。

相关内容

最新更新