最新公告
  • 欢迎您光临网站无忧模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 为什么nodejs里面可以直接使用module?

    正文概述 掘金(前端关宇)   2020-12-13   558

    node 遵循的是CommonJS规范, 为了避免全局命名冲突,以及同名函数名或者变量名被覆盖的情况,提出了module的概念,并且内部实现了,每个js是个独立的modlue,内部的变量和方法都是私有的,其他模块要用的话,自己要先通过module关键字导出,其他模块要用的话要用require导入。

      1. require的时候,nodejs做了什么
      1. module module.export是什么关系
      1. 为什么可以直接使用module module.exports 以及二者直接是什么关系? 为什么可以直接使用 __dirname __filename?
      1. 循环引用的问题

    一个例子

    • A 会报错The argument 'id' must be a non-empty string. Received , 报错的信息在nodejs源码里面写着 为什么nodejs里面可以直接使用module? 所以直接require('') 会走到nodejs内部Modlue原型上的require方法里面,会先判断传入的路径是否为空, 为空就报错,停止往下执行。
    • (function (exports, require, module, __filename, __dirname) { var a = ;
    • 因为,nodejs会把exports ,require, modlue当参数导入进来, 所以我们可以在写js的时候,直接使用。
    • 那我们可以直接打印这几个变量,看看他们是什么关系
    // console.log(module);
    
    // Module {
    //   id: '.',
    //   exports: {},
    //   parent: null,
    //   filename:
    //    '/Users//development//nodeFromStratch/005.require.js',
    //   loaded: false,
    //   children: [],
    //   paths:
    //    [ '/Users//development//nodeFromStratch/node_modules',
    //      '/Users//development//node_modules',
    //      '/Users//development//node_modules',
    //      '/Users//development/node_modules',
    //      '/Users//node_modules',
    //      '/Users/node_modules',
    //      '/node_modules' ] }
    
    • 发现是个Modlue对象里面有个属性,exports 值是{} 这就解释了为什么,我们导入变量或者函数的时候要这么写了
    var url = "test.com";
    
    function logUrl(message) {
      //do something
      console.log("log method invoked");
      console.log(message);
    }
    
    module.exports.log = logUrl;
    module.exports.SomeUrl = url;
    
    
    • 调用的堆栈信息从下往上为: startup-> Module.runMain-> Module._load等一系列过程。
    
    //b.js
    var a =;
    
    
    //报错信息
    (function (exports, require, module, __filename, __dirname) { var a = ;
                                                                          ^
    
    SyntaxError: Unexpected token ;
        at new Script (vm.js:80:7)
        at createScript (vm.js:274:10)
        at Object.runInThisContext (vm.js:326:10)
        at Module._compile (internal/modules/cjs/loader.js:664:28)
        at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
        at Module.load (internal/modules/cjs/loader.js:600:32)
        at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
        at Function.Module._load (internal/modules/cjs/loader.js:531:3)
        at Function.Module.runMain (internal/modules/cjs/loader.js:754:12)
        at startup (internal/bootstrap/node.js:283:19)
    

    nodejs requirejs大概原理

    • 当我们写个nodejs文件的时候。站在nodejs角度,他大概做了这些事:
    //自己实现的例子
    function require() {
      var modlue = {
        exports: {}
        // ... //省略其他属性和方法
      };
      (function(modlue, exports) {
        //用户写的js被包装在这里
        var a = 1;
    
        modlue.exports.a = 1;
      })(modlue, modlue.exports);
    
      return modlue.exports;
    }
    
    console.log(require());//{ a: 1 }
    
    
    
    //node官网的例子
    To illustrate the behavior, imagine this hypothetical implementation of require(), which is quite similar to what is actually done by require():
    
    function require(/* ... */) {
      const module = { exports: {} };
      ((module, exports) => {
        // Module code here. In this example, define a function.
        function someFunc() {}
        exports = someFunc;
        // At this point, exports is no longer a shortcut to module.exports, and
        // this module will still export an empty default object.
        module.exports = someFunc;
        // At this point, the module will now export someFunc, instead of the
        // default object.
      })(module, module.exports);
      return module.exports;
    }
    
    

    require怎么用,用在文件的哪里?

    • require的使用非常简单,它相当于module.exports的传送门,module.exports后面的内容是什么,require的结果就是什么,对象、数字、字符串、函数……再把require的结果赋值给某个变量,相当于把require和module.exports进行平行空间的位置重叠。

    而且require理论上可以运用在代码的任何地方,甚至不需要赋值给某个变量之后再使用,比如:

    require('./a')(); // a模块是一个函数,立即执行a模块函数
    var data = require('./a').data; // a模块导出的是一个对象
    var a = require('./a')[0]; // a模块导出的是一个数组
    

    你在使用时,完全可以忽略模块化这个概念来使用require,仅仅把它当做一个node内置的全局函数,它的参数甚至可以是表达式

    require(process.cwd() + '/a');
    
    或者 
    
    

    nodejs如何解决循环引用的问题?官网给出的是 unfinished copy

    • 看一个例子 a.js require b.js 同时b.js 引用a.js
    //a.js
    var b = require("./b");
    console.log("in a.js get b is :" + b.b);
    module.exports.a = "this is a";
    
    //in b.js get a is :undefined
    // in a.js get abis :this is b
    
    
    // b.js 
    var a = require("./a");
    console.log("in b.js get a is :" + a.a);
    module.exports.b = "this is b";
    
    //运行a .js 结果是有个没有输出
    
    //in b.js get a is :undefined
    // in a.js get abis :this is b
    
    
    //如何解决? 修改a b 中 先导出 再 reqiure 
    
    //a.js
    module.exports.a = "this is a";
    
    var b = require("./b");
    console.log("in a.js get  b is :" + b.b);
    
    
    //b.js
    module.exports.b = "this is b";
    
    var a = require("./a");
    console.log("in b.js get a is :" + a.a);
    
    
    //再次运行a .js 得到结果为
    
    in b.js get a is :this is a
    in a.js get  b is :this is b
    
    //再次运行b.js   得到结果为
    
    in a.js get  b is :this is b
    in b.js get a is :this is a
    

    总结

      1. 为什么nodejs可以使用module ? 因为nodejs包装了一层,包装的时候传入了module ,require,等参数
    • modlue 和module.exports 关系是? var module = { exports: {}} 这样的关系
    • 所以不要写exports.xx = {} 这种 会覆盖引用,应该写 modlue.exports.xxKey = xxValue modlue.exports.xxKey1 = xxValue1 或者 modlue.exports = { key1: val1, key2:val2, ...}
    • node如何解决循环引用的问题?写的时候尽量避免,或者先导出 再require (有待再次验证)
    • 感谢阅读,希望有帮助。

    参考

    • nodejs官网
    • nojejs源码 reqiure node/-/blob/lib/internal/modules/cjs/helpers.js#L16:3
    • nodejs vm vm.runInThisContext

    下载网 » 为什么nodejs里面可以直接使用module?

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元