前端模块化规范

模块化

概念

模块化就是将一个复杂的程序按照一定的规则封装成几个块,并组合在一起。块的内部数据与实现是私有的, 只是向外部暴露一些接口与外部其它模块通信。

优势

1、避免命名冲突
2、更好的分离,按需加载
3、更高复用性
4、高可维护性


script 标签

最初模块化的雏形是使用 script 标签,将每个 js 文件看作不同的模块,加载进来。

缺点

1、污染全局作用域。
2、开发人员必须手动解决模块和代码库的依赖关系。
3、文件必须按照 script 标签的书写顺序进行加载。
4、在大型项目中各种资源难以管理,长期积累的问题导致代码库混乱。
5、同步加载,易造成阻塞。

解决

1、defer:只支持IE,脚本不会改变文档的内容,脚本文件设置为延迟加载,当浏览器遇到带有 defer 属性的 script 标签时,会再开启一个线程去下载 js 文件,同时继续解析 HTML 文档,等 HTML 全部解析完毕、DOM 加载完成之后,再去执行加载好的js文件。

<script type="text/javascript" defer></script>

2、async:HTML5 新增的属性,仅适用于外部脚本,async 属性也是会开启一个线程去下载 js 文件,但它会在下载完成后立刻执行,而不是会等到 DOM 加载完成之后再执行,所以还是有可能会造成阻塞

<script type="text/javascript" async></script>

规范

1、CommonJS

语法

导入:require()

导出:module.exports、exports

应用

Node.js(服务端)

特点

1、this 指向当前模块
2、运行时同步加载,返回的是个对象。CommonJS脚本代码在require的时候,就会全部执行。只有加载完成,才能执行后面的操作,易造成阻塞。
3、加载的是整个模块,将所有接口全部加载进来,不会污染全局作用域。
4、输出的是一个值的拷贝
5、按路径加载模块,根据实际文件名缓存,而不是 require() 提供的参数缓存的。
6、模块加载的顺序,按照其在代码中出现的顺序。

2、ES6模块化

语法

导入:

import xxx from
import {xxx} from

导出:

export { xxx, yyy };
应用

原生JS

特点

1、this指向undefined
2、编译时输出接口,异步加载,适用于浏览器和服务端。
3、可以单独加载其中的某个接口(方法)。
4、静态分析,动态引用,不允许修改。输出的是值的引用
5、通过 babel 将未被宿主环境直接支持的 ES6 模块 编译为 ES5 的 CommonJS。

babel 本质:将不被支持的 import/export 翻译成已被支持的 require/exports。

3、AMD(异步模块定义)

语法

定义:define 将代码定义为模块

define(['module1'], function(n){
   return 模块
})

导入:require 引入需要的模块

require(['module1'], function(n){
   使用 n
})
应用

RequireJS

特点

1、异步加载模块,适用于浏览器端,允许指定回调函数。
2、依赖前置,在定义模块的时候就要声明其依赖的模块。
3、不会污染全局环境,能够清楚地显示依赖关系。
4、输出的模块兼容CommonJS。

4、CMD(通用模块定义)

语法

导出:

exports.xxx = value

导入:

var module = require('./module')
//引入依赖模块(异步)
require.async('./module1', function (n) {})
应用

SeaJs

特点

1、异步加载,模块使用时才会加载执行,适用于浏览器端。
2、就近依赖,只有在用到某个模块的时候再去require。

5、UMD

AMD和CommonJS的糅合

实现

1、先判断是否支持Node.js模块(exports是否存在),存在则使用Node.js模块模式。
2、再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
3、否则将模块公开到全局(window或global)。

(function (window, factory) {
    if (typeof exports === 'object') {     
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {     
        define(factory);
    } else {     
        window.eventUtil = factory();
    }
})(this, function () {
    // module ...
});

require 和 import 区别

1、require 输入的变量是简单赋值,浅拷贝,可以修改;import 输入的变量是只读的,不允许修改,只允许修改对象的属性。
2、require 在运行时才知道加载那个模块;而 import 会将加载的模块提升到整个模块的头部,首先执行,即在编译时执行。
3、require 可以写进表达式和变量中;而 import 不能。

module.exports 和 exports 区别

1、 exports 对象 和 module.exports 对象,指同一个内存空间。
2、 module.exports 对象才是真正的暴露对象,而 exports 对象是 module.exports 对象的引用 ,不能改变指向,只能添加属性和方法,若直接改变 exports 的指向,则会返回空对象。

参考文章:https://www.jianshu.com/p/08ae4f9fa802https://segmentfault.com/a/1190000017466120https://developer.51cto.com/art/202103/654008.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值