好家伙,今天疯狂联系各种部门,终于!终于给我看到了一捏捏离开的希望!希望30号能顺利离开呜呜呜呜呜
目录
模块化
接下来记录了我学习到的关于老模块化,和新模块化的一捏捏比较浅的内容~
模块化的前世今生——前世
早期的网页中,是没有一个是实质的模块规范的,整个大环境都一片混沌,那时的程序猿们实现模块化的方法,就是最原始的通过script标签来引入多个js文件,node.js是09年诞生的,随着JavaScript项目越来越复杂,模块化的需求早已迫在眉睫。这种原始的方法也带来了很多问题:
1、无法选择要引入模块的那些内容(要么全引,要么一个都不能引)
2、在复杂的模块场下非常容易出错
......总之就是各种的不好
于是乎,悲催的程序猿们就急急急需在JavaScript中引入一个模块化的解决方案!但是在ES6标准诞生前的6年里,JavaScript中一直都没有一个内置的模块化系统。于是各路大神开始着手自定义了一个又一个模块化系统,而CommonJS便是从无数自制模块化系统中杀出的佼佼者。
模块化的前世今生——今生
node自己的模块化规范方案ES6是2015年才诞生,而node中默认支持的模块化规范叫做ComminJS,没错!就是那冲出重围的非官方程序猿做的CommonJS。有没有发现怪怪的地方呢?在node里拥有两套模块规范,一个是官方的ES6,一个是被默认支持的CommonJS。
CommonJS规范
默认情况下,node中的模块化标准是MCommonJS,在CommonJS中,一个js文件就是一个模块。
导出模块
在定义模块时,模块内部任何变量或其他对象都是私有的,不会暴露给外部模块,可以通过exports来设置要向外部暴露的内容。exports:表示导出,本身就是一个对象。在CommonJS模块化规范中,在模块内部定义了一个module对象,module对象内部存储了当前模块的基本信息,同时module对象中有一个属性名为exports,exports用来指定需要向外部暴露的内容。只需要将需要暴露的内容设置为exports或exports的属性,其他模块即可通过require来获取这些暴露的内容。
哔哔叭叭一大堆,反正就是可以用下面两个方法哈!
- 可以通过exports来设置要向外部暴露的内容
- exports.a = XXX
- module.exports = {}
咱定义叫m1.js的模块
- exports.a = XXX
//向外部暴露的方式
//可以通过exports 一个一个的导出值
exports.a = "勺子"
exports.b = "芍子"
exports.c ={name:"勺子想返京"}
exports.d = function fn() {
console.log("QAQ");
}
//此时打印的console.log(m1),返回 {a: '勺子', b: '芍子', c: {…}, d: ƒ}
- module.exports = {}
//也可直接通过module.exports同时导出多个值(对象.属性)
//把abcd对象直接赋值给exports修改这个属性
module.exports = {
a: "勾子",
b:"苟子",
c:[1,2,3,4],
d:() => {
console.log(111);
}
}
//此时打印的console.log(m1),返回 {a: '勾子', b: '苟子', c: Array(4), d: ƒ}
然后咱在需要调用m1模块的文件里调用他俩是这么调用的哈(下文会讲到引入模块的方法)
//引入自定义模块时
const m1 = require("./m1.js")
console.log(m1); //返回 所有m1的值
m1.d() //返回 m1里d的值
问题出现了!可以用exports同时导出多个值咩?比如像👇酱紫:
exports = {
a: "勾子",
b:"苟子",
c:[1,2,3,4],
d:() => {
console.log(111);
}
}
//返回的还是一个空对象: {}
当然是不可以捏,上面会返回一个空对象。
module.exports{},改的是对象。改对象的时候,所有指向该对象的都会受到影响,所以在别的模块里引用m1的时候,它也会看到这个修改。
exports = {},改的是变量。这是给一个变量赋值时,只会影响变量自己,这是改变量,所以这里只是给exports赋值了而已。
引入模块
模块最重要的就是,能在别的文件里引用它,能把多个模块组装在一起。
使用require("模块的路径")函数来引入模块,有好几种引入模块方式,分别是:
1、引入自定义模块时
2、引入核心模块时
3、引入文件夹模块时
引入自定义模块时
- 模块名要以 ./ 或 ../开头 const m1 = require("./m1.js")
- 扩展名可以省略 const m1 = require("./m1")
- 在ComminJS中,如果省略了js文件的扩展名时,node,会自动为文件补全扩展名,优先寻找.js,再.json,再.node
//引入自定义模块时
const m1 = require("./m1.js")
console.log(m1)
m1.d()
- 只想引用一捏捏module.exports{}里的东西时,有如下两种方法
- 取出来单独赋值
- 解构赋值(js基础里的东东昂)
//把m3里的name取出来并赋值给Name
const Name = require("./m3").name
console.log(Name)
//解构赋值
const {name,age} = require("./m3")
console.log(name,age)
引入核心模块时(node自带的模块)
- 直接写核心模块的名字即可
- 也可以在核心模块前添加node: (查找速度会快一捏捏)
//引入核心模块时
const path = require("path")
console.log(path)
//const path = require("node:path")
引入文件夹模块时
- 默认的入口文件是index
//引入文件夹模块时
const hello = require("./hello") //相当于引入 ./hello/index.js
console.log(hello);
CommonJS模块的运行原理
module、exports、require,他们仨因为可以直接使用,就很像全局变量有木有!但实际上它们是作为实参传入进来的。所有的CommonJS的模块都会被包装到一个函数中:
(function(exports, require, module, __filename, __dirname) {
// 模块代码会被放到这里
});
//- __filename表示当前模块的绝对路径
//- __dirname表示当前文件夹的路径(当前模块所在目录的路径)
范例:
(function(exports, require, module, __filename, __dirname) {
let a = 10
let b = 20
});
//证明它是运行到函数里,只需要找遇到一个只有函数里有的东西——arguments(所有的实参都会分装在这里面)
console.log(arguments);
//返回显示有5个参数
ES6规范
默认情况下,node中的模块化标准是MCommonJS,Node.js默认并不支持ES模块化,要想使用ES的模块化,可以采用以下两种方案:
- 使用mjs作为扩展名
- 修改package.json将模块化规范设置为ES模块
package.json - 描述当前项目的(描述当前项目文件夹里所有文件的)
当我们设置 "type":"module" 当前项目下所有的js文件都默认为ES module
ES模块化,在浏览器中同样支持,但是通常我们不会直接使用,因为在浏览器当中运行,就需要考虑兼容性的问题,通常都会结合打包工具使用。
导出模块
// 导出变量(命名导出)
export let name1, name2, …, nameN;
export let name1 = …, name2 = …, …, nameN;
// 导出函数(命名导出)
export function functionName(){...}
// 导出类(命名导出)
export class ClassName {...}
// 导出一组
export { name1, name2, …, nameN };
// 重命名导出
export { variable1 as name1, variable2 as name2, …, nameN };
// 解构赋值后导出
export const { name1, name2: bar } = o;
// 默认导出
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
// 聚合模块
export * from …; // 将其他模块中的全部内容导出(除了default)
export * as name1 from …; // ECMAScript® 2O20 将其他模块中的全部内容以指定别名导出
export { name1, name2, …, nameN } from …; // 将其他模块中的指定内容导出
export { import1 as name1, import2 as name2, …, nameN } from …; // 将其他模块中的指定内容重命名导出
export { default, … } from …;
引入模块
// 引入默认导出
import defaultExport from "module-name";
// 将所有模块导入到指定命名空间中
import * as name from "module-name";
// 引入模块中的指定内容
import { export1 } from "module-name";
import { export1 , export2 } from "module-name";
// 以指定别名引入模块中的指定内容
import { export1 as alias1 } from "module-name";
import { export1 , export2 as alias2 , [...] } from "module-name";
// 引入默认和其他内容
import defaultExport, { export1 [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
// 引入模块
import "module-name";
注意:
通过ES模块化,导入的内容都是常量。常量不能改变量,但是可以改对象。
重命名
通过as指定别名
import {a as hello, b, c} from "./m4.mjs"
console.log(hello)
通过import * 改所有引入
但!开发时要尽量避免import * 的情况,这东西写后端还好,但是如果是用node写前端,那它就是一个非常可怕的存在。这么写表示,我要把m4模块当中的所有内容都引进来,统一放入一个叫M4的对象当中。
import * as M4 from "./m4.mjs"
console.log(M4.b)
核心模块
核心模块是node中的内置模块,这些模块有的可以直接在node中使用,有的直接引入即可使用。核心模块有很多,很多很常用,比如Process、Path、Fs,核心模块的学习我写在下一个里面哈(因为我还没有学捏,而且我的大作业里正好用的就有它们)
好困,今天好困困,社区说已经把我的名单报给文旅局什么的了,我现在希望不要出什么差批,30号可以顺利离开呜呜呜