0

JS模块化 - 冰大墩

 1 year ago
source link: https://www.cnblogs.com/taotaoFrontEndDevelopment/p/16950389.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

模块化规范

1.CommonJS规范#

​ 在node中,默认支持的模块化规范叫做CommonJS,

​ 在CommonJS中,一个js文件就是一个模块

  • CommonJS规范

      • 使用require('模块的路径')函数来引入模块

      • 引入自定义模块时

        • 模块名要以 ./ 或 ../ 开头
        • 扩展名可以省略
          • 在CommonJS中,如果省略的js文件的扩展名,node会自动不全扩展名
            • 如果没有改js文件,会找名字相同的文件进行引入
      • 引入核心模块时

        • 直接写核心模块的名字即可
        • 也可以在核心模块前添加node:可以加快查询效率
    //引入自定义模块
    const m1 = require("./m1")
    //按需引入
    const name = require('./m1').name
    const {name,age,gender} = require('./m1')
    //引入核心模块
     const path = require("path")
     const path = require("node:path")
    

    在定义模块时,模块中的内容默认是不能被外部看到的

    ​ 可以通过exports来设置要向外部暴露的内容

    访问exports的方式有两种:

    1. exports
    2. module.exports
    • 当我们在其他模块中引入当前模块时,require函数返回的就是exports -
    • 可以将希望暴露给外部模块的内容设置为exports的属性
    ------------------------------m1.js----------------------------------------
    // 可以通过exports 一个一个的导出值
    // exports.a = "孙悟空"
    // exports.b = {name:"白骨精"}
    // exports.c = function fn(){
    //     console.log("哈哈")
    // }
    
    // 也可以直接通过module.exports同时导出多个值
    module.exports = {
        a: "哈哈",
        b: [1, 3, 5, 7],
        c: () =>{
            console.log(111)
        }
    }
    
    

    CommonJS执行原理:

    1. 所有的CommonJS的模块都会被包装到一个函数中

      (function(exports, require, module, __filename, __dirname){
          //模块代码会被放到这里
      })
      

      exports:用来设置模块向外部暴露的内容

      require:用来引入模块的方法

      module:当前模块的引用

      __filename:模块的路径

      __dirname:模块所在目录的路径

2.ES6模块化#

Node.js中同样支持ES模块化,使用模块化无非就是需要注意两件事导出和导入

  1. // 导出变量(命名导出)
    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 …; 
    
  2. // 引入默认导出
    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";
    

    需要注意的是,Node.js默认并不支持ES模块化,如果需要使用可以采用两种方式:

    1. 方式一:直接将所有js文件修改为mjs扩展名。
    2. 方式二:修改package.json中type属性为module。

3.核心模块#

核心模块,是node中自带的模块,可以在node中直接使用

  1. window 是浏览器的宿主对象 node中是没有的
  2. global 是node中的全局对象,作用类似于window
  3. ES标准下,全局对象的标准名应该是 globalThis
  • process

    • 表示当前的node进程

    • 可以通过改对象获取进程的信息,或者对进程做各种操作

      1. process是一个全局变量,可以直接使用

      2. 有哪些属性和方法:

        1. process.exit([code状态码])

          1. 结束当前进程,终止node
        2. process.nextTick(callback[ ...args])

          1. 将函数插入到 tick队列中

          2. tick队列中的代码,会在下一次事件循环之前执行,会在微任务队列和宏任务队列中任务之前执行

            setTimeout(()=>{
            	console.log('111')
            }) //宏任务队列
            queueMicrotask(()=>{
                console.log('222')
            })  //微任务队列
            process.nextTick(()=>{
                console.log('333')
            })
            console.log('444')
            
            
            //执行顺序为: 444 -> 333 -> 222 -> 111
            

      执行顺序:

      1. tick队列(了解)
      2. 微任务队列
      3. 宏任务队列
  • path模块

    • 表示的路径

    • 通过path可以用来获取各种路径

    • 要使用path,需要先对其进行引入

      • path.resolve([...paths])

        • 用来生成一个绝对路径
        • 直接调用resolve,则返回当前的工作目录
        • 注意,我们通过不同的方式执行代码时,它的工作目录是有可能发生变化的
      • 如果将一个相对路径作为参数:

        • 则resolve会自动将其转换为绝对路径
        • 此时根据工作目录的不同,他所产生的绝对路径也不同
      • 一般会将一个绝对路径作为第一个参数

        • 一个相对路径作为第二个参数
        • 这样它会自动计算出最后的路径
      //引入模块
      const path = require('node:path')
      //以后在使用路径时,尽量通过path.resolve()来生成路径
      const result = path.resolve(__dirname, './hello.js')
      
  • fs模块

    • fs用来帮助node来操作磁盘中的文件

    • 文件操作也就是所谓的I/O流,input output

    • 使用fs模块,同样需要引入

    • fs.readFileSync()

      • readFileSync() 同步的读取文件的方法,会阻塞后面的代码执行

      • 当我们通过fs模块读取磁盘中的数据时,读取到的数据总会一Buffer对象的形式返回

      • Buffer是一个临时用来存储数据的缓冲区

        //引入模块
        const path = require('node:path')
        const fs = require('node:fs')
        const buffer = fs.readFileSync(path.resolve(__dirname, './hello.txt'))
        console.log(buffer.toString())  //把Buffer数据转换为字符串类型
        
    • fs.readFile()

      • 异步的读取文件的方法

        • 方法1:回调函数式

          const path = require('node:path')
          const fs = require('node:fs')
          fs.readFile(path.resolve(__dirname, './hello.js'),(err,buffer)=>{
              if(err){
                   console.log("出错了~")
              } else {
                   console.log(buffer.toString())
              }
          })
          
        • 方法2:promise式

          const path = require('node:path')
          const fs = require('node:fs/promises')
          fs.readFile(path.resolve(__dirname, './hello.js'))
          	.then(buffer=>{
              	console.log(buffer.toString())
          	})
          	.catch(e=>{
              	console.log('出错了,有问题', e.message)
          	})
          
        • 方法3:async和await式

          ;(async ()=>{
              try {
                  const buffer = await fs.readFile(path.resolve(__dirname, './hello.js'))
                  console.log(buffer.toString())
              } catch(e){
                  console.log(’出错了....)
              }
          })()
          
    • fs.appendFile()

      • 创建新文件,或将数据添加到已有文件中
    • fs.mkdir()

    • fs.rmdir()

    • fs.rm()

    • fs.rename()

    • fs.copyFile()

  1. //实现复制一个文件
    //1.读取文件中的内容
    const path = require('node:path')
    const fs = require('node:fs/promises')
    fs.readFile(path.reslove(__dirname, './hello.txt'))
    	.then(buffer =>{
        	//2.复制文件中的
        	return fs.appendFile(path.resolve(__dirname, './world.txt'), buffer)
    	})
    	.then(()=>{
        	console.log('操作结束')
    	})
    	.catch(err =>{
        	console.log('出错了..')
    	})
    

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK