在线学习Node.js——Day7之模块化

好家伙,今天疯狂联系各种部门,终于!终于给我看到了一捏捏离开的希望!希望30号能顺利离开呜呜呜呜呜


目录

模块化

模块化的前世今生——前世

模块化的前世今生——今生

CommonJS规范

导出模块

引入模块

CommonJS模块的运行原理

ES6规范

导出模块

引入模块

重命名

核心模块


模块化

接下来记录了我学习到的关于老模块化,和新模块化的一捏捏比较浅的内容~

模块化的前世今生——前世

早期的网页中,是没有一个是实质的模块规范的,整个大环境都一片混沌,那时的程序猿们实现模块化的方法,就是最原始的通过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号可以顺利离开呜呜呜

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值