JavaScript模块化学习

本文深入探讨JavaScript模块化的概念和实现,包括模块的作用、为何需要模块化,以及CommonJS和ES6模块化的规范和区别。CommonJS常用于Node.js环境,而ES6模块化是现代浏览器的原生支持。浏览器端可通过Browserify将CommonJS转换为可执行代码。此外,文章还强调了模块化带来的代码复用、命名冲突避免和加载优化等优势。
摘要由CSDN通过智能技术生成

JavaScript模块化学习

资料

JavaScript modules 模块 - JavaScript | MDN (mozilla.org)

Module 的语法 - ECMAScript 6入门 (ruanyifeng.com)

什么是模块

把一些复杂的程序根据一定的规则拆分乘多个单个文件,并最终组合在一起。

这些被拆分出来的文件是模块,模块内部数据是私有的,只有向外部暴露一些方法才能与外部其他模块进行通行。

Node.js 已经提供这个能力很长时间了,还有很多的 Javascript 库和框架 已经开始了模块的使用(例如, CommonJS 和基于 AMD 的其他模块系统 如 RequireJS, 以及最新的 WebpackBabel

好消息是,最新的浏览器开始原生支持模块功能了,这是本文要重点讲述的。这会是一个好事情 — 浏览器能够最优化加载模块,使它比使用库更有效率:使用库通常需要做额外的客户端处理。

为什么要模块化

  1. 降低代码的复杂度,提高解耦性。高内聚,低耦合。如果一个文件是写的一个功能,那么它是不能在拆分的,只能提高它的内聚性,让代码配合更加紧密。低耦合,不同功能点(模块)之间,把修改的影响降到最低。[高内聚低耦合_百度百科 (baidu.com)](https://baike.baidu.com/item/高内聚低耦合#:~:text=高内聚低耦合,是 软件工程 中的概念,是判断软件设计好坏的标准,主要用于程序的 面向对象 的设计,主要看类的内聚性是否高, 耦合度 是否低。. 目的是使程序模块的可重用性、移植性大大增强。.,外文名. High cohesion %26 Low coupling. 范 围.)
  2. 避免命名冲突。特别人是多人开发的时候,特别容易命名冲突。
  3. 更好的分离,按需加载,而不是怼一堆的js文件在页面(多个script标签)。
  4. 提高代码的复用性,高维护性。

模块化规范

现在较为流行的模块化规范是 CommonJS(既可以写浏览器端的代码,也可以写nodejs的代码)、ES6、AMD (异步加载,在浏览器端)。

CommonJS

规范

CommonJS规范 – JavaScript 标准参考教程(alpha) (ruanyifeng.com)

  1. 每一个文件都是模块。
  2. CommonJS 模块化的代码可以在服务端运行,也能在浏览器端运行
  3. 服务器端:模块化的代码可以直接运行。
  4. 浏览器端:模块化的代码要经过Browserify编译运行

需要注意的是,如果引用使用CommonJS规范引入模块,那么引入的那个模块文件中的所有代码都会运行一次,不管某些内容是否被暴露。

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。

基本语法

下述的代码都是在node端运行的,如果不是将会做出说明。

1. 暴露语法

module.exports = value;

exprort.xxx = value;

并且最终暴露出的是module.exports,而不是exports。

2. 内置关系

image-20211127185831227

我们使用代码验证它们两个指向的是否为同一个对象。

console.log(module.exports === exports);

image-20211127190352115

确实是指向的同一个对象。但是浏览器是没有这两个东西的。

image-20211127190551156

3. 引入语法

require命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错。

const xxx = require("模块的路径");// xxx 最好与模块名相同
let name = 'fjx';
let age = 21;
let obj = {
    say : function () {
        console.log("你好的!");
    }
}
// 写多个不会多个暴露。赋值操作啊
// 暴露,不暴露的内容是不会被外部引用的,而且使用CommonJS引用模块的时候模块里面的所以代码都是运行一次的
//module.exports = obj;

//module.exports.a = obj;

 exports.a = obj  //必须这么写

// 最后暴露出去的是 module.exports


exports.sum = function () {
    let ans = 0;
    for(let i=0; i<arguments.length; i++){
        ans += arguments[i];
    }
    return ans;
}
// 暴露的是 module.exports指向的对象
// 如果module.exports = newObj; 那么 exports.xxx = asd; 这个暴露就没有用了,引用的知识
// 所以别混用,尽量只用一个

引入的代码

const {person,sum} = require('./module1');
console.log(module.exports === exports);
console.log(person);


// require 的导入路径的问题

// requir 导入第三问文件

为什么不能这样设置exports = xxx,这样设置的结果就是引用的使用空对象{}。原因如下:

exports = module.exports = {},而且最后返回的是module.exports的内容

exprots 和 module.exports 都是对一个空对象的引用,那么既然exports = xxx,就意味着它不在指向那个空对象了,所以返回的就是一个空对象,而不是设置的值。

但是使用module.exports = xxx 就可以正确返回,这是应该返回的就是module.exports,与初始的那个空对象没有关系了。

这里有几点注意:

  • 如果没有加文件后缀,会按照以下顺序后缀加载文件
    • .js fs模块同步读取文件编译执行
    • .json fs模块同步读取文件,用JSON.parse()解析返回结果,它返回的是一个对象,而且json文件不需要使用暴露。
    • .node 这是c/c++编写的扩展文件,通过dlopen()方法编译
  • 其他扩展名 会以.js文件载入
  • 如果是文件夹则会默认加载该文件夹下 package.json 文件中 main 属性对应的文件(一般是index.js)
  • 根据这个查找顺序,如果不是核心模块或者安装的模块(也就是所加了路径的,是"./xxx"或者加了路径的require),如果文件和文件夹同名,先查找文件再是文件夹。
  • 如果 main 属性对应的文件不存在,则自动找 index.js index.json
  • 如果是内置模块或者是 npm 安装的模块,直接使用包名字即可(不需要路径,而且不需要加.js,我们是通过对于包文件夹下的的package.json中的main中的xxx.js 去加载包的,切记,加了.js 还会报错,因为node_modules 下根本就没有你要的包.js文件,而在是在对应的文件夹下),其实就是引用了那个包的package.json里面的main
  • npm 引入包时,如果当前文件夹下的 node_modules 没有,则会自动向上查找(所以就不要加路径了,要不然无法自动向上找)

image-20211128114201991

4. CommonJS的拷贝机制

拷贝机制是浅拷贝,如果某个模块中的引用类型的属性或者方法发送变化,那么外部引用这个模块的数量或者方法也会发生变化,但是基本数据类型就不会存在这个问题。

5.在浏览器端使用CommonJS

在浏览器端是没有module.exportsexportsrequire的,所以要使用一个库browserify

下载Browserify

yarn global add browserify

编译指定的文件

browserify 指定路径下的文件(使用require的那个文件) -o 指向路径下的文件

image-20211127202220469

大致原理就只作者写了一个require吧。

这样浏览器就可以正常使用了。

ES6模块化

阮一峰大佬已经总结的很好了,直接读它的文章即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值