概要:nodejs是一个基于Google V8引擎开发的一个javascript运行环境
特性:事件驱动 非阻塞 IO
直接在命令行通过 node命令 + 文件名的方式来执行js文件
可以省略文件后缀名 因为nodejs就是用来运行js文件的
理解:每一个js文件就是一个模块
使用:通过require来引入模块 exports或者module导出模块
模块化规范:
commonJS (nodejs所使用的规范 require/export)
定义:一个单独的js文件就是一个模块,加载模块需要使用require方法、而加载过来的是改模块中使用exports所导出的对象
特性:commonJs加载模块是同步的所以只有模块记载完毕后才会去执行、而想nodejs这种做服务的的加载模块都是从本地硬盘去加载所以相对较快不同考虑异步问题 但如果是web端的话加载模块都要到服务器加载比较慢不可能等所有模块加载完后再执行。
AMD (异步模块 requireJs所使用的规范)
定义:AMD是通过difine方法定义模块通过require方法加载模块 AMD加载模块是通过回调函数来加载所有模块 把每个模块它所依赖的模块都传到参数中后再加载 也就是在解析和执行当前模块之前,必须指明当前模块所依赖的模块
使用方式:在html中使用requireJs加载:
<script data-main="main" src="require.js"></script>
我们需要使用 data-main来指定一个主模块来作为加载模块的入口文件
CMD (通用模块 懒加载 Common Module Definition)
定义:与CommonJS Modules/1.1 和 Node Modules 规范类似 也是一个文件为一个模块 CMD相对比较简单清晰 就是在你什么时候要使用就通过define(factory)加载 factory是一个函数 里面会默认传入3个参数 require exports module 可以使用require在来加载模块
CMD与AMD区别:
例:
// AMD define(['./a,' .'/b'], function(a ,b) { // 依赖已经明确写好 .......... }) // CMD define(function(require, exports, module) { var a = require('./a'); // 随时加载 var b = require('./b'); })
问题1:在web端js中为什么没有require、exports等变量而nodejs中可以使用这些变量呢?
其实每一个js文件都运行在一个函数里 我们可以打印出这个函数看看长啥样。
创建一个js文件其内容如下:
console.log(arguments.callee.toString());
在命令行运行该文件
返回以下内容:
function (exports, require, module, __filename, __dirname) { console.log(arguments.callee.toString());}
可以看到这个函数里有五个参数:
1 export 就是我们用来导出的变量
2 require 用来引入模块的函数
3 module 模块对象
4 __filename 当前文件路径 包含自身文件名
5 __dirname 当前文件绝对路径
这样可以使我们的每个模块之间的变量相互独立互不影响
问题2:require和exports又是怎么实现导入导出模块的呢?
首先一个js文件的执行必然只有两种情况
导入导出过程分析:
1.执行js文件前先在外部定义一个module对象大致内容如下:
var module = { exports:{} filename:"" ...... }
2.把文件内容放到一个如上面的函数里执行并传入module、 module.export、require、filename、dirname五个参数;
这样我们在使用module.exports或者exports导出变量的时候
因为module是引用值 所以就是在修改外部定义好的module对象的exports属性
例:在module.js文件导出内容如下:
exports.a = 10;
这时的module 对象:
module = { exports:{ a: 10 } }
而我们在使用require导入的时候就是用以上步骤执行这个js文件后把module.exports的值返回
例:在module1.js中内容如下:
const a = require("./module.js"); // 返回 {a:10}