美文网首页
NodeJS学习笔记——CommonJS

NodeJS学习笔记——CommonJS

作者: JacobMa1996 | 来源:发表于2017-07-15 11:13 被阅读0次

    前言

    陆陆续续两三天,一直在寻找好的学习资源,想跟着一套视频一直学习完整个系列过程,NodeJS发展实在太快,很多资源教程使用的版本,官方文档就已经更新换代,直接看官网的文档,又太过枯燥无味,特别是对于我从前端转过来,没有后端基础,对于很多概念不理解,直接看文档和源码也很难看懂.
    实践又无从下手,所以结合网上良莠不齐的技术博客,教程书籍,视频实战,进行一个Node核心技术的学习,往后再是站点的搭建,希望在这过程中的关键知识点都能够做一个记录。

    CommonJS

    概念

    Node应用由模块组成,采用CommonJS模块规范,为解决全局变量污染的问题;
    JS作为函数是编程语言,支持闭包,把一段JS代码用函数包装起来,其所有全局变量就变成了函数的局部变量,每个函数作为一个模块,互相调用来实现模块机制;
    根据这个规范,每个文件就是一个模块;

    //example.js
    var x = 5;
    var addX = function (value) {
        return value + x;
    };
    
    module.exports.x = x;
    module.exports.addX = addX;
    
    //client.js
    var example = require('./example');
    
    console.log(example.x);
    console.log(example.addX(1));
    

    CommonJS的模块特点:

    • 所有代码都运行在模块作用域,不会污染全局作用域。
    • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
    • 模块加载的顺序,按照其在代码中出现的顺序。

    原理

    Node内部提供一个Module构建函数,所有模块都是Module的实例;
    每个module对象,代表当前模块,都有以下属性:

    • module.id 模块的识别符,通常是带有绝对路径的模块文件名。
    • module.filename 模块的文件名,带有绝对路径。
    • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
    • module.parent 返回一个对象,表示调用该模块的模块。
    • module.children 返回一个数组,表示该模块要用到的其他模块。
    • module.exports 表示模块对外输出的值。
    // example.js
    var jquery = require('jquery');
    exports.$ = jquery;
    console.log(module);
    
    { id: '.',
      exports: { '$': [Function] },
      parent: null,
      filename: '/path/to/example.js',
      loaded: false,
      children:
       [ { id: '/path/to/node_modules/jquery/dist/jquery.js',
           exports: [Function],
           parent: [Circular],
           filename: '/path/to/node_modules/jquery/dist/jquery.js',
           loaded: true,
           children: [],
           paths: [Object] } ],
      paths:
       [ '/home/user/deleted/node_modules',
         '/home/user/node_modules',
         '/home/node_modules',
         '/node_modules' ]
    }
    

    exports AND module.exports

    module通过其属性exports对外暴露要要输出的内容:

    module.exports.x = x;
    

    为了方便,Node为每个模块提供了一个exports变量,指向module.exports,等同于在每个模块的头部,添加了这样一行代码:

    var exports = module.exports;
    

    所以在对外输出接口时,也可以使用exports;

    exports.x = x;
    

    通过给exports的属性赋值,等同于给module.exports这个空对象添加属性和值;
    但是,不能直接对exports赋值,因为在Node内部保存的是module对象,而对exports直接赋值,exports就不再指向module.exports这个对象,也就切断了exports和module.exports的联系;

    require

    require命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错。

    根据参数的不同格式,require命令去不同路径寻找模块文件。

    • 如果参数字符串以“/”开头,则表示加载的是一个位于绝对路径的模块文件。比如,require('/home/marco/foo.js')将加载/home/marco/foo.js。

    • 如果参数字符串以“./”开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如,require('./circle')将加载当前脚本同一目录的circle.js。

    • 如果参数字符串不以“./“或”/“开头,则表示加载的是一个默认提供的核心模块(位于Node的系统安装目录中),或者一个位于各级node_modules目录的已安装模块(全局安装或局部安装)。

    • 如果参数字符串不以“./“或”/“开头,而且是一个路径,比如require('example-module/path/to/file'),则将先找到example-module的位置,然后再以它为参数,找到后续路径。

    • 如果指定的模块文件没有发现,Node会尝试为文件名添加.js、.json、.node后,再去搜索。.js件会以文本格式的JavaScript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。

    • 如果想得到require命令加载的确切文件名,使用require.resolve()方法。

    模块加载机制和缓存机制后面再更新;

    参考文章:
    http://javascript.ruanyifeng.com/nodejs/module.html
    http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001434502419592fd80bbb0613a42118ccab9435af408fd000

    相关文章

      网友评论

          本文标题:NodeJS学习笔记——CommonJS

          本文链接:https://www.haomeiwen.com/subject/rdyahxtx.html