当前位置: 代码迷 >> 综合 >> Node 中 CommonJS 规范
  详细解决方案

Node 中 CommonJS 规范

热度:34   发布时间:2023-09-06 12:44:16.0

CommonJS 是一个很大的规范 Node 和浏览器只是借用了它的一部分精华

先来Node环境运行的结果:

# a.jsconsole.log('我是a.js')

无引用的情况:

# b.jsconst lib = require('./a')
console.log('我是b.js')# 运行b.js我是a.js
我是b.js

有引用的情况:

# b.jsconst lib = require('./a')
console.log('我是b.js',lib)# 运行b.js我是a.js
我是b.js {} //得到一个空对象

exports 情况,通过 exports 定义模块的输出:

# a.jsexports.hello='world!' // 这里可以挂载合法的数据类型,对象、字符串、函数等
console.log('我是a.js')
# b.jsconst lib = require('./a')
console.log('我是b.js',lib)# 运行b.js我是a.js
我是b.js { hello: 'world!' } //得到一个含有 key 的对象 `key` 就是挂载到 `exports` 上的属性名

b.js require 的引用和 a.js exports 的引用是不是同一个引用?

# a.jsexports.hello='world!'
console.log('我是a.js')
setTimeout(()=>{console.log(exports)
},1000)
# b.jsconst lib = require('./a')
console.log('我是b.js',lib)
lib.addNewProperty = '我是b.js中新增加的属性'# 运行b.js我是a.js
我是b.js { hello: 'world!' }# 一秒后输出 说明  exports 导出的引用和 require 得到的引用是同一个引用
{ hello: 'world!', addNewProperty: '我是b.js中新增加的属性' } 

如果直接导出一个函数该怎么办? exports.function?

a.jsexports.hello='world!'console.log('我是a.js')module.exports = function test(){console.log('我是a.js导出的function')
}
b.jsconst lib = require('./a')
console.log('我是b.js',lib)
lib.addNewProperty = '我是b.js中新增加的属性'
console.log(lib.hello)
console.log(lib)# 运行b.js我是a.js
我是b.js function test(){console.log('我是a.js导出的function')
}
undefined // 拿不到 exports 的引用 // addNewProperty 挂载到了 module.exports 上
{ [Function: test] addNewProperty: '我是b.js中新增加的属性' } // module.exports 会覆盖 exports 的内容 

Node 中 ES6 模块和 CommonJS 采用各自的加载方案。

CommonJS 模块的输出都定义在 module.exports 这个属性上面。Nodeimport 命令加载 CommonJS 模块,Node 会自动将module.exports 属性当作模块的默认输出,即等同于 export default xxx

前端可以借助 Webpack 利用 CommonJS 的规范书写代码,Webpack 会把所有的 CommonJS 分析一遍然后生成一个大的 js,所有的文件成为一个对象{./index.js:(function(modeule,exports,__webpack_require__){文件内容}}),./xxx.js:(function(modeule,exports){文件内容}}) 通过这种形式为每个文件创建了一个作用域。

  • CommonJS
    // a.js
    module.exports = {foo: 'hello',bar: 'world'
    };// 等同于
    export default {foo: 'hello',bar: 'world'
    };
    

总结

  • 改变 require 的对象原对象也会受影响(值引用)
  • exportsrequirejs 默认的是一个空对象,对象里面可以有函数
  • exports 通过 exports.xx 导出对象,所有的导出都挂载exports这个对象上,require输入默认的是一个空对象,通过这种方式定义一个对象的输出
  • modules.exports可以直接导出一个函数
  • exportsmodule.exports同时存在时只会导出 module.exports的内容,会覆盖exports
  • import 输出的是值得引用(复制一份地址)
  相关解决方案