JavaScript是没有命名空间的,解决方案就是下面的代码,我们称之为揭示模块模式.
/**
* 模块模式
*/
const module = (()=>{
const privateFoo = () => {/*...*/}
const privateBar = [];
const exported = {
publicFoo: () => {/**...*/},
publicBar: () => {/**...*/}
};
return exported;
})();
console.log(module);
这个模块模式利用自执行函数创建的私有作用域,module函数只会导出拥有的模块,对于闭包内部变量,外部是无法访问的,这个就是nodejs模块化的基础.
CommonJs是一个旨在标准化JavaScript生态系统的团队,nodejs就是在这个基础上构建了模块化机制.
const fs = require('fs');
/**
* 模块模式
*/
const _module = (()=>{
const privateFoo = () => {/*...*/}
const privateBar = [];
const exported = {
publicFoo: () => {/**...*/},
publicBar: () => {/**...*/}
};
return exported;
})();
console.log(
exports
);
function loadModule(file, module,require) {
const wrappedSrc=`(function (module, exports, require) {
${fs.readFileSync(file, 'utf-8')}
})(module, module.exports, require);`;
eval(wrappedSrc);
}
loadModule('t.js')
modules.js源码简化版如下:
require仅仅只存在于模块内部的变量
console.log(require);
打印结果如下
{
// [Function: require]
resolve: {
// [Function: resolve]
// paths: [Function: paths]
},
main: /*Module*/ {
id: '.',
exports: {},
parent: null,
filename: '/Users/pengliheng/www/adb/index.js',
loaded: true,
children: [],
paths: [
'/Users/pengliheng/www/adb/node_modules',
'/Users/pengliheng/www/node_modules',
'/Users/pengliheng/node_modules',
'/Users/node_modules',
'/node_modules'
]
},
extensions:{
'.js': [Function],
'.json': [Function],
'.node': [Function]
},
cache:{
'/Users/pengliheng/www/adb/index.js': /*Module*/ {
id: '.',
exports: { },
parent: null,
filename: '/Users/pengliheng/www/adb/index.js',
loaded: true,
children: [],
paths: [Array]
}
}
}
查找路径次序,依次查找本地,,本地的上层路径.
'/Users/pengliheng/www/adb/node_modules',
'/Users/pengliheng/www/node_modules',
'/Users/pengliheng/node_modules',
'/Users/node_modules',
'/node_modules'
一直找到父元素的顶级目录,依然找不到变量,这个时候就应该去查找全局模块,
1: $HOME/.node_modules 2: $HOME/.node_libraries 3: $PREFIX/lib/node
但是就我自己的macbook来说,真实的全局安装路径是: /usr/local/bin
console.log('================================================');
console.log(module);
console.log('================================================');
console.log(require);
console.log('================================================');
console.log(__filename);
console.log('================================================');
console.log(__dirname);
console.log('================================================');
console.log(process === global.process);
console.log('================================================');
一个是读取的,另一个是缓存的,但是并没有看到其他文件的缓存.
顺序依次是 js => json => .node
在相同目录下依次有以下文件
首先s不带后缀的文件会和s文件夹相冲突,具体原因我也不清楚,文件目录如下 优先读取本地文件,没有的话再读取文件夹的
{
id: '.',
exports: {},
parent: null,
filename: '/Users/pengliheng/www/adb/index.js',
loaded: false,
children: [],
paths: [
'/Users/pengliheng/www/adb/node_modules',
'/Users/pengliheng/www/node_modules',
'/Users/pengliheng/node_modules',
'/Users/node_modules',
'/node_modules'
],
}
(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
1.让模块的顶级变量不是全局变量,而仅仅只是模块内的变量 2.可以更加方便的使用一些模块内部的顶级变量 - 这相当于模块内部的全局变量,但是在每个模块内部,这个变量代表了不同的值
__dirname 当前模块的文件夹路径 __filename 当前模块的文件路径 require module exports
[ '/Users/pengliheng/www/adb/node_modules',
'/Users/pengliheng/www/node_modules',
'/Users/pengliheng/node_modules',
'/Users/node_modules',
'/node_modules',
'/Users/pengliheng/.node_modules',
'/Users/pengliheng/.node_libraries',
'/usr/local/Cellar/node/10.10.0/lib/node' ]
当层层向上还拿不到模块的时候,就会去.nide_modules里面拿,其实全局模块会去系统工具里面拿...
app.js
exports.dirname = __dirname;
exports.filename = __filename;
exports = { // 这样赋值无效
dirname: __dirname,
filename: __filename,
}
module.exports.app = 'app'
index.js
const app = require('./app');
console.log(
app
);
console.log => result
{
dirname: '/Users/pengliheng/www/adb/app',
filename: '/Users/pengliheng/www/adb/app/index.js',
app: 'app'
}