web前端开发之JavaScript:Node.js模块化
【摘要】 node.js的模块化简介
Node模块化
Node.js 有一个简单的模块加载系统,遵循的是 CommonJS 的规范。 在 Node.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。
Escript标准缺陷(Es5之前)
没有模块系统
标准库较少
没有标准接口
缺乏管理系统
模块化
为什么需要模块化? --> 开发规模日渐庞大 ,在浏览器中,顶层作用域的变量是全局的,所以项目稍微复杂点,如果引用的 js 非常多的时候,很容易造成命名冲突,然后造成很大意想不到的结果。为了避免全局污染,JS 前辈们想了很多办法,也就是前端的模块化的演变过程
什么是模块化?--> 最基本模块化是将代码分割为多个原文件机制
模块化的好处? --> 可复用代码、拥有独自作用域,变量命名互不干扰
Node 在加载 JS 文件的时候,自动给 JS 文件包装上定义模块的头部和尾部
// nodejs 会自动给我们的js文件添加头部,见下行
(function(exports, require, module, __filename, __dirname) {
// 这里是你自己写的js代码文件
}); // 自定添加上尾部
Node会自动给js文件模块传递的5个参数,每个模块内的代码都可以直接用。而且你也看到了,代码都会被包装到一个函数中,所以代码的作用域都是在这个包装的函数内,这点跟浏览器的window全局作用域是不同的。
模块内的参数说明:
__dirname: 当前模块的文件夹名称
__filename: 当前模块的文件名称---解析后的绝对路径。
module: 当前模块的引用,通过此对象可以控制当前模块对外的行为和属性等。
require:是一个函数,帮助引入其他模块.
exports:这是一个对于 module.exports 的更简短的引用形式,也就是当前模块对外输出的引用。
CommonJS规范
CommonJS规范的提出,主要是为了弥补Es6之前JS没有模块化标准的缺陷
CommonJS规范为JS制定了一个美好愿景,希望JS能狗崽任何地方运行。
CommonJSCommonJS规范对模块的定义十分简单:
模块引用 --> 提供require()方法引用模块
模块定义 --> Node中一个文件就是一个模块
exports对象导出当前模块的变量或方法
module对象,代表模块自身,exports是module对象的属性
模块标识 --> 即模块名,传递给require()方法的参数(需符合驼峰命名法的字符串,或是以.或..开头的相对路径;绝对路径亦可)
Node的模块实现
Node中虽然使用的是CommonJS规范,但是自身也对规范做了一些取舍
在Node中引入模块,需要经历如下3个步骤:
路径分析
文件定位
编译执行
在Node中,模块分为三大类:
由底层C++编写的内建模块
由Node提供的核心模块
由用户编写的文件模块
模块引用、定义
一个js文件就是一个模块
每一个js文件中的js代码都是独立运行在一个函数内中的
暴露属性:
exports.x = 10;
暴露方法:
exports.fn = function(){};
每个js文件其实相当于写在function(){js模块代码};
所以在js模块中定义的变量和函数在其他模块中是无法访问的
可以通过exports向外部暴露属性和方法
通过require()函数来引入外部的模块
require()可以传递一个文件的路径作为参数,node将会自动根据该路径来引入外部模块
这里路径,如果使用相对路径,必须以.或..开头
使用require()引入模块以后,该函数会返回一个对象,这个对象代表的是引入的模块
引入:
var md = require("./02.module.js")
md可以更换为其它的名称使用:
console.log(md.x)
Node模块化中所声明的变量都为局部变量(原理:其实是运行在函数中的代码块)。
证明方式1:
let a = 10;
console.log(a); // 10
console.log(global.a); // undefined
证明方式2:
console.log(arguments.callee + "");
模块化的本质:封装的独立函数作用域的特性
function (exports, require, module, __filename, __dirname) {
// coding...
}
require()引用
// 引用自定义模块
// require("./module1.js");
// 亦可忽略 .js 后缀名
// require("./module1");
// 引用模块,并接收所引用模块暴露的对象
let module1 = require("./moudle1");
// 引用核心模块 或 node_modules文件内的第三方模块,无须添加路径地址,直接写包名即可。
let fs = require("fs");
module.exports导出
// 方式1:
module.exports.a = 10;
module.exports.fn = () => {
console.log("fn...");
}
// 方式2:
module.exports = {
a: 10,
fn() {
console.log("fn");
}
}
exports导出
exports.a = 10;
exports.fn = () => {
console.log("fn...");
}
P.x exports 无法直接导出一个对象, 因为是 module.exports的引用
__filename 当前文件所在路径(绝对路径)
__dirname 当前文件所在文件夹路径(绝对路径)
Exports和module
exports
helloModule.js
exports.name = "孙悟空"; exports.age = 18; exports.sayName = function(){ console.log("我是孙悟空~~~"); };
05.module.js
var hello = require("./helloModule"); console.log(hello.name); console.log(hello.age); hello.sayName();
module.exports
helloModule.js
module.exports.name = "孙悟空"; module.exports.age = 18; module.exports.sayName = function(){ console.log("我是孙悟空~~~"); };
输出结果并不会变
区别
以下代码使用module.export=不会出错,使用export=程序报错
helloModule.js
module.exports = { name:"猪八戒"; age:28; sayName:function(){ console.log("我是猪八戒") } };
为什么使用export会出错
基本数据类型 和 引用数据类型 之间的问题
栈内存(独立) 和 堆内存(指向) 的问题 (关闭浏览器才释放内存的特性)
exports = module.exports
通过export只能使用对象.属性来赋值 (修改对象的属性)
module.exports 即可以通过对象.属性赋值,也可以直接赋值 (即可以修改对象的属性,也可以修改对象)
module.exports.xxx = xxxx;
module.exports = { xx:xx;xxx:xxx;};
var obj = {};
obj.a = {};
var a = obj.a;
// a 和 obj.a 指向的是同一个对象
// console.log(a == obj.a); // 返回 true
a.name = "孙悟空";
a = new Object();
console.log(obj.a.name); // 孙悟空
console.log(a.name); //undefined
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)