一篇彻底了解node模块化引用

node有个很重要的概念,模块系统

  • 模块作用域
  • 使用require来加载模块
  • 使用exports接口对象来导出

模块作用域

我们知道node中没有DOM和BOM,但在node中,node为js提供了很多服务器api,此类api绝大多数被包装到了具名的核心模块中,比如文件操作fs模块,server服务http模块,os操作系统信息模块

想使用模块,我们都需要在文件中用require来引入模块

var  fs = require('fs')
var  http = require('http')
var  os = require('os')

每块核心模块都是控制一方面内容的,比如os系统

var os =require('os')
// 获取cpu信息
console.log(os.cpus())
// 获取当前操作系统总内容大小
console.log(os.totalmem())

在node中有两种模块,具名的模块(fs,os,http, path)、自己编写的模块(后缀名可以省略)

加载自己编写的模块必须用相对路径,尤其是同级目录下,也要用./,不然会单做核心模块来查找,不存在则会报错

require(./demo.js)

在node中,只有模块作用域,没有全局作用域,这和浏览器不一样

有时候加载模块并不是为了执行代码,而是使用某个信息,所以模块通信变得十分的重要

加载 require

  • 加载文件并执行,文件作用域(不会有污染的情况)

  • 通信规则

    • 加载require(优先从缓存加载)

    • 导出,拿到被加载文件模块的接口对象(从对象中获取,未导出的内部模块信息无法共享)

      exports默认是个空对象

  • 模块加载规则

    如果是非路径形式的模块标识,node会当成核心或者第三方模块

    ./当前目录不可省略,文件后缀名可以省略

    这里也说明一个情况就是第三方模块不可能和核心模块同一个名字

导出 exports

node中的模块作用域

导出多个对象
exports.a,exports.b,exports.c,
导出单个对象
module.exports = 'hello'

以下情况后者会覆盖前者

module.exports = 'hello'
module.exports = 'hello1111'

当然,也可以导出多个方法

module.exports = {
    a,
    b,
    c
}

原理深入浅出

在node中,每个模块都有自己的module对象,该module对象都有一个成员叫exports也是一个对象

var module = {
    exports: {
        foo: 'bar
    }
}
exports.foo ='bar'

谁来require 我, 谁就得到module.exports,默认代码的最后一句, return module.exports

每次导出接口成员的时候,module.exports.xxx很麻烦,node为了简化操作,专门提供了变量

var exports = module.exports

一定要记住最后 return的事 module.export不是exports