上一篇讲了模块是如何被寻找到然后加载进来的,这篇则是如何导出属性方法以及自定义模块后缀等一系列模块问题。
exports 对象
这是最常见的对象了,以往导出都是这样写的。
1 | // a.js |
一直都是这么用非常简单,但是不能直接用对象覆盖他,如下代码是不对的。
1 | // a.js |
为什么不能直接覆盖呢,因为 exports
只是 module.exports
对象的引用。
module.exports
对象
如果要导出一整个对象或者构造函数之类的,就需要用到 module.exports
对象了。
1 | // a.js |
导出构造函数:
1 | // klass.js |
module 其他属性
module 还有些其他属性,简单说下吧。
module.id
模块id,往往是模块路径module.children
子模块module.filename
模块路径module.loaded
是否加载完毕module.parent
父模块module.paths
各级 node_modules 目录路径
require 函数
说模块,当然离不开 require
函数,除了加载模块之外,他还有一些其他用法。
require.resolve
不会加载执行,只会返回模块的绝对路径。require.cache
缓存所有已经加载的模块,如果你要更新模块就要删除这里的缓存。
1 | var a = require('./a'); |
虽然不清楚什么时候用,但是至少是这么用的,删除缓存后,下次加载这个模块,就会重新加载模块文件了。
require.extensions
自定义模块后缀
还有个 require.extensions
非常好用的属性,但遗憾的是官方提示弃用了这个属性,不过值得庆幸的是,这个属性永远不会被移除,只是不推荐使用而已。
我第一次注意到这个属性是在 ejs 源码里,当时很好奇这是个什么东西,去翻了下官方文档,发现捡到宝了。后来又发现 node 命令行下的 babel 模块也注册了自定义模块,后缀分别是 .es
, .es6
, .jsx
,可以直接 require('./a.es6')
或者是 require('./a.jsx')
得到编译好的 js 代码。
好了,不说废话了,来看个官方简单例子吧。
1 | require.extensions['.json'] = function(module, filename) { |
这是 node 源码的 json 模块实现,我只是删除了一个 stripBOM 函数,为了方便大家理解。
当然官方不推荐这样做是有道理的,官方推荐编译为兼容的 js 代码模块运行,性能更佳,而不应该采用这样的自定义模块实现。
不过看用途而定了,有时候也不一定追求极致的性能。