commonJs规范

339 阅读3分钟

exports

  1. 当一个模块被其他模块引用 会执行这个模块 并默认导出是一个空对象

    // index.js
    const lib = require('./lib')
    console.log('引入的lib: ', lib) // 引入的lib: {}
    
    // lib.js
    console.log("hello, I'm lib") // 被引入时会执行该模块,打印hello, I'm lib
    
  2. exports指定模块的输出 (导出的是个对象 默认是{}) 可以在exports对象上,指定属性

    • exports.key = value 导出的是个json, 形如{ key: value }, key为json的key value是值,可以是基本类型, 也可以是对象或者函数
      // index.js
      const lib = require('./lib')
      console.log('引入的lib: ', lib) // 引入的lib: { hello: word }
      
      // lib.js
      exports.hello = 'word'
      
    • 可以导出多个属性
      // index
      const lib = require('./lib')
      console.log('引入的lib:', lib) // 引入的lib { hello: 'word', sum: [Function], info: { name: 'test', version: '1.1.1' } }
      
      // lib
      exports.hello = 'word'
      exports.sum = function (a, b) { return a + b }
      exports.info = { name: 'test', version: '1.1.1' }
      
  3. 当前模块的exports的引用 和 其他模块require的结果, 是否是同一个引用?
    是同一个引用

    // index
    const lib = './lib'
    lib.addtional = 'test' // 在index模块 去修改lib模块 打印可以看到会影响到lib模块
    
    // lib
    exports.hello = 'word'
    console.log(exports) // { hello: 'word' }
    setTimout(() => {
      console.log(exports) // { hello: 'word', addtional: 'test' }
    }, 2000)
    
    

module

  1. module 结构
    // module对象默认是一个 Module实例
    // lib-module
    console.log(module)
    /*
     Module {
       id: '', // filename(好像不是哦 因为还有一个filename的属性)
       path: '', dirname
       exports: {}, // 1.默认是一个空对象, 可以通过exports.key挂载属性; 2.当定义了module.exports时, 该属性就指向module.exports
       parent: Module {}, // 父级module, 引入这个模块的模块(在这里是main中引入了lib-module, 所以parent: 指向的是main的module)
       filename: '',
       loaded: false,
       children: [], // [ [Circular] ]
       paths: []
     }
    */
    
    
  2. module.exports属性
    • 当没有定义module.exports时, 则module.exports 指向的是exports对象。
      // main
      const lib_module = require('./lib_module')
      console.log(lib_module) // {hello: 'word'}
      
      // lib_module
      exports.hello = 'word'
      console.log(module) // Module {..., exports: { hello: word }, ... }
      

      如果在main.js中, 给引入的lib_module添加属性, lib_module.js的exports和module.exports都会添加到这个属性

      // main
      const lib_module = require('./lib_module')
      lib_module.addtional = 'test'
      
      
      // lib_module
      exports.hello = 'word'
      console.log(module) // Module {..., exports: { hello: word }, ... }
      setTimout(() => {
        console.log(exports) // { hello: 'word', addtional: 'test' }
        console.log(module) // Module {..., exports: { hello: 'word', addtional: 'test' }, ... }
      })
      
      
    • 定义了module.exports, 则module.exports 指向的是定义的module.exports
      // main
      const lib_module = require('./lib_module')
      
      // lib_module
      exports.hello = 'word'
      module.exports = { lastName: 'Chen', fistName: 'YiXun' }
      console.log(exports) // { hello: 'word' }
      console.log(module) // Module {..., { lastName: 'Chen', fistName: 'YiXun' }, ...}
      
    • module.exports 导出一个函数, 给引入的lib_module模块添加属性
      // main
      const lib_module = require('./lib_module')
      console.log(lib_module) // [Function: sum]
      lib_module.addtional = 'test'
      console.log(lib_module) // [Function: sum] { addtional: 'test' }
      
      // lib_module
      module.exports = function sum (a, b) { return a + b }
      setTimout(() => {
        console.log(module) // Module { ..., exports: [Function: sum] { addtional: 'test' }, ... }
      })
      
    • 定义了多个module.exports, 后定义的会覆盖之前定义的
      // main
      const lib_module = require('./lib_module')
      console.log(lib_module) // { test: '覆盖成功' }
      
      // lib_module
      module.exports = function sum (a, b) { return a + b }
      module.exports = { test: '覆盖成功!' }
      
    • module.exports导出可以是任意值, 包含基本类型, module.exports导出的是什么, require到的就是什么
      // main
      let lib_module = require('./lib_module')
      console.log(lib_module) // 'aa'
      
      // lib_module
      module.exports = 'aa'
      
  3. module.exports指定的模块输出和require的模块引用, 是同一个引用吗
    是同一个引用
    
     // main
    const lib_module = require('./lib_module')
    lib_module.addtional = 'test'
    
    // lib_module
    exports.hello = 'word'
    module.exports = { lastName: 'Chen', fistName: 'YiXun' }
    setTimout(() => {
      console.log(module) // Module { ..., exports: { lastName: 'Chen', fistName: 'YiXun' }, ... }
      console.log(exports) // { hello: 'word' }
    })
    

注意: 不管是exports, 还是module.exports, require到的和导出的对象都是同一个引用 修改了引入的模块的对象的属性, 模块就会对应该变;但是直接修改指向是不生效的: 这点不难理解, 因为修改属性lib_module.key = ..., 此时lib_modulerequire同一个引用;而一旦执行lib_module = ...时, lib_modulerequire就不是同一个引用了 lib_module.test = '添加属性成功', 则lib_module.js里会给module的exports对象加test属性; 而lib_module = {test: 'change' }, 是不会lib_module.js的module.exports 修改为{ test: 'change' }