在Node js中识别本机函数的通用方法

时间:2014-12-29 09:37:10

标签: node.js

是否有任何通用的方法来识别Node.js中的本机函数?

例如,要在浏览器中测试本机功能,我会使用此功能 - function isNative(fn) { return (/{\s*[native code]\s*}/).test('' + fn); }

我们可以使用类似的东西来检测本地Node.js函数,例如fs.readFile等等吗?

我想一种方法是在程序启动之前检查缓存GLOBAL变量中可用的函数,是否有更优雅的方法?

谢谢!

2 个答案:

答案 0 :(得分:0)

问题是节点的内置函数在技术上是非本机的(对于v8)。唯一的方法是检查函数原始文件名:

var FunctionOrigin = require('function-origin');
var natives = process.binding('natives');

function isNative(fn) {
  var file = FunctionOrigin(fn).file;
  var noExt = file.slice(0, file.length - 3);

  return natives.hasOwnProperty(noExt);
}


function Test(){}


console.log(isNative(require('fs').readFile));
console.log(isNative(Test));

答案 1 :(得分:-1)

解决方案的另一种可能的方法(并且绝对不是优雅'):检查所有标准Node.js包及其功能名称(我从Node准备了v0.10.35的标准模块列表。根据Node' s recomendations on Core Modules)的js github /lib文件夹。

不幸的是,Node.js不会在require.cache中保存有关已加载核心模块的信息,因此无法通过这种方式检测它们。

函数testNative()检测几乎所有本地的'函数,除了require()(可能还有一些其他函数在JavaScript上编写并位于Node.js模块之外)。

评论:

  1. 我在函数testNative()中填充native_fns数组。如果它很慢,您可以在函数外部提取此部分。
  2. 该函数使用eval()检测已加载的模块,因此您需要遵循正确的命名规则。
  3. 因此,仅当您始终对库变量使用标准变量名时,测试函数才有效:

    var fs = require('fs');    // good
    var myfs = require('fs');  // bad
    

    更新: 这个丑陋的部分可以替换为 process.moduleList 的分析。

    代码:

    function testNative(fn) { 
        if(!!fn.toString().match(/{\s*\[native code\]\s*}/)) return true;
    
        var std_modules = ['assert','buffer','child_process','cluster','console','constants',
           'crypto','dgram','dns','domain','events','freelist','fs','http','https','module',
           'net','os','path','punycode','querystring','readline','repl','smalloc','stream',
           'string_decoder','sys','timers','tls','tracing','tty','url','util','vm','zlib',
            'Math','JSON'];
    
        var native_fns = [];
        for(var i=0; i<std_modules.length;i++) {
            try {
               var module = eval(std_modules[i]);
                native_fns.push(module);
                if(module) {
                    for(var k in module) {
                         native_fns.push(module[k]);
                    }
                }
            } catch (err) {}
        }
    
        return  native_fns.indexOf(fn) > -1;
    }
    
    // Test
    function foo() {return 1};
    var fs = require('fs');
    
    console.log(testNative(fs.readFile));    // true
    console.log(testNative(foo));            // false
    console.log(testNative(JSON.stringify)); // true