JS模块化—CJSAMDCMDES6-前端面试知识点查漏补缺

news2024/11/18 16:49:31

本文从以时间为轴从以下几个方面进行总结JS模块化。从无模块化 => IIFE => CJS => AMD => CMD => ES6 => webpack这几个阶段进行分析。

历史

幼年期:无模块化

方式

  1. 需要在页面中加载不同的js,用于动画,组件,格式化
  2. 多种js文件被分在了不同的文件中
  3. 不同的文件被同一个模板所引用
<script src="jquery.js"></script>
<script src="main.js"></script>
<script src="dep1.js"></script>

此处写法文件拆分是最基础的模块化(第一步)

* 面试中的追问

script标签的参数:async & defer

<script src="jquery.js" async></script>

总结

  • 三种加载
  1. 普通加载:解析到立即阻塞,立刻下载执行当前script
  2. defer加载:解析到标签开始异步加载,在后台下载加载js,解析完成之后才会去加载执行js中的内容,不阻塞渲染
  3. async加载:(立即执行)解析到标签开始异步加载,下载完成后开始执行并阻塞渲染,执行完成后继续渲染

image.png

  • 兼容性:> IE9

  • 问题可能被引导到 => 1. 浏览器的渲染原理 2.同步异步原理 3.模块化加载原理

  • 出现的问题

  1. 污染全局作用域

成长期(模块化前夜) - IIFE(语法测的优化)

image.png

作用域的把控

let count = 0;
const increase = () => ++count;
const reset = () => {
    count = 0;
}

利用函数的块级作用域

(() => {
    let count = 0;
    ...
})
//最基础的部分

实现一个最简单的模块

const iifeModule = (() => {
    let count = 0;
    const increase = () => ++count;
    const reset = () => {
        count = 0;
    }
    console.log(count);
    increase();
})();
  • 追问:独立模块本身的额外依赖如何优化

优化1:依赖其他模块的传参型

const iifeModule = ((dependencyModule1,dependencyModule2) => {
    let count = 0;
    const increase = () => ++count;
    const reset = () => {
        count = 0;
    }
    console.log(count);
    increase();
    ...//可以处理依赖中的方法
})(dependencyModule1,dependencyModule2)

参考 前端进阶面试题详细解答

面试1:了解jquery或者其他很多开源框架的模块加载方案

将本身的方法暴露出去

const iifeModule = ((dependencyModule1,dependencyModule2) => {
    let count = 0;
    const increase = () => ++count;
    const reset = () => {
        count = 0;
    }
    console.log(count);
    increase();
    ...//可以处理依赖中的方法
    return 
        increase,reset
    }
})(dependencyModule1,dependencyModule2)
iifeModule.increase()

=> 揭示模式 revealing => 上层无需了解底层实现,仅关注抽象 => 框架

  • 追问:
  1. 继续模块化横向展开
  2. 转向框架:jquery|vue|react模块细节
  3. 转向设计模式

成熟期

image.png

CJS (Commonjs)

node.js指定

特征:

  1. 通过module + exports对外暴露接口
  2. 通过require去引入外部模块,

main.js

const dependencyModule1 = require('./dependencyModule1')
const dependencyModule2 = require('./dependencyModule2')

let count = 0;
const increase = () => ++count;
const reset = () => {
    count = 0;
}
console.log(count);
increase();

exports.increase = increase;
exports.reset = reset;

module.exports = {
    increase, reset
}

exe

const {increase, reset} = require(./main.js)

复合使用

(function(this.value,exports,require,module){
    const dependencyModule1 = require('./dependencyModule1')
    const dependencyModule2 = require('./dependencyModule2')
}).call(this.value,exports,require,module)

追问:一些开源项目为何要把全局、指针以及框架本身作为参数

(function(window,$,undefined){
    const _show = function(){
        $("#app").val("hi zhuawa")
    }
    window.webShow = _show;
})(window,jQuery)

阻断思路

  • 一. window

    1. 全局作用域转换为局部作用域,window是全局作用域,如果不转成局部作用域会有一个向上查找知道全局的过程,提升执行效率
    2. 编译时优化:编译后会变成(优化压缩成本,销毁)
    (function(c){})(window) // window会被优化成c
    //window在里面所有别的执行所有的变化都会随着执行完毕都会跟着c一起被销毁
    
  • 二. jquery

    1. 独立定制复写和挂载
    2. 防止全局串扰
  • 三. undefined
    防止改写:在执行内部这段代码的时候保证undefined是正确的,不会被改写,如在外部定义一个undefined =1
    undefined对jquery本身是一个很重要的一个存在

优缺点

  • 优点:CommonJS率先在服务端实现了,从框架层面解决了依赖,全局变量未然的问题
  • 缺点: 针对服务端的解决方案,异步拉取,依赖处理不是很友好

=> 异步依赖的处理

AMD

通过异步执行 + 允许指定回调函数
经典实现框架:require.js

新增定义方式:

//define来定义模块
define(id, [depends], callback)
//require来进行加载
reuqire([module],callback)

模块定义的地方

define('amdModule',[dependencyModule1,dependencyModule2],(dependencyModule1,dependencyModule2) => {
    //业务逻辑
    let count = 0;
    const increase = () => ++count;
    module.exports = {
        increase
    }
})

引入的地方

require(['amdModule'],amdModule => {
    amdModule.increase()
})

面试题:如果在AMDModule中想兼容已有代码,怎么办?

define('amdModule',[],require => {
    const dependencyModule1 = require('./dependencyModule1')
    const dependencyModule2 = require('./dependencyModule2')
    //业务逻辑
    let count = 0;
    const increase = () => ++count;
    module.exports = {
        increase
    }
})

面试题:手写兼容CJS&AMD

//判断的关键:
    1. object还是function
    2. exports ?
    3. define

(define('AMDModule'),[],(require,export,module) => {
    const dependencyModule1 = require('./dependencyModule1')
    const dependencyModule2 = require('./dependencyModule2')

    let count = 0;
    const increase = () => ++count;
    const reset = () => {
        count = 0;
    }
    console.log(count);
    export.increase = increase();
})(
    //目标:一次性区分CJS还是AMD
    typeof module === 'object' && module.exports && typeof define !== function ? //CJS
    factory => module.exports = factory(require,exports,module)
    : //AMD
    define
)

优缺点

  • 优点:适合在浏览器中加载异步模块的方案
  • 缺点:引入成本

CMD

按需加载
主要应用框架:sea.js

define('module',(require,exports,module) => {
    let $ = require('jquery')
    let dependencyModule1 = require('./dependencyModule1')
})

优缺点

  • 优点:按需加载,依赖就近
  • 缺点:依赖打包,加载逻辑存在于每个模块中,扩大了模块体积,同时功能上依赖编译

ES6模块化

新增定义:

  • 引入:import
  • 引出:export

面试:

  1. 性能 - 按需加载
// ES11原生解决方案
import('./esMModule.js').then(dynamicModule => {
    dynamicModule.increase();
})

优点:
通过一种统一各端的形态,整合了js模块化的方案
缺点:本质上还是运行时分析

解决模块化新思路 - 前端工程化

遗留

根本问题:运行时进行依赖分析
解决方案:线下执行

编译时依赖处理思路

<script src="main.js"></script>
<script>
  // 给构建工具一个标识位
  require.config(__FRAME_CONFIG__);
</script>
<script>
  require(['a', 'e'], () => {    // 业务逻辑
  })
</script>

define('a', () => {
    let b = require('b')
    let c = require('c')
})

完全体:webpack为核心的前端工程化 + mvvm框架的组件化 + 设计模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/11400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件测试】一个边界值事故,领导leader心里苦季度奖金没了还被罚3K......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 项目组长&#xff1…

java类的练习--下面给出一个根据雇员类型利用多态性完成

java类的练习–下面给出一个根据雇员类型利用多态性完成… 题目 ​ 下面给出一个根据雇员类型利用多态性完成工资单计算的程序。定义一个类Employee作为超类&#xff0c;Employee的子类有Boss&#xff08;每星期发给他固定工资&#xff0c;而不计工作时间&#xff09;、Piece…

顶级“Redis学习笔记”,缓存雪崩+击穿+穿透+集群+分布式锁,NB了

如果你是一位后端工程师&#xff0c;面试时八成会被问到 Redis&#xff0c;特别是那些大型互联网公司&#xff0c;不仅要求面试者能简单使用 Redis&#xff0c;还要深入理解其底层实现原理&#xff0c;具备解决常见问题的能力。可以说&#xff0c;熟练使用 Redis 就是后端工程师…

超140支爆款B站恰饭,2022年B站双11战报来了!

- 导语 从0到3.06亿月活&#xff0c;从“与世无争”到今天手持高粘性、高活跃的用户参战双十一&#xff0c;在B站的品牌们有了更成熟的营销模式。 2022年双十一已经落下帷幕&#xff0c;在B站全面拥抱双十一的火热氛围下&#xff0c;有哪些品牌做到了声量、销量双丰收&#x…

【毕业设计】深度学习人脸表情识别系统 - python

文章目录0 前言1 技术介绍1.1 技术概括1.2 目前表情识别实现技术2 实现效果3 深度学习表情识别实现过程3.1 网络架构3.2 数据3.3 实现流程3.4 部分实现代码4 最后0 前言 &#x1f525; Hi&#xff0c;大家好&#xff0c;这里是丹成学长的毕设系列文章&#xff01; &#x1f5…

基于 BERT 实现的情感分析(文本分类)----概念与应用

文章目录基于 BERT 的情感分析(文本分类)基本概念理解简便的编码方式: One-Hot 编码突破: Word2Vec编码方式新的开始: Attention 与 Transformer 模型四方来降: 超一流预处理模型 BERT 诞生BERT 实现情感分析数据预处理并创建数据集定义网络模型定义训练函数与评估函数设置损失…

AVL树的插入(C++实现)

1. 概念 AVL树&#xff08;Adelson-Velsky and Landis Tree&#xff09;于1962年被提出&#xff0c;是计算机科学中最早被发明的平衡二叉查找树。AVL树得名于它的发明者G. M. Adelson-Velsky和Evgenii Landis。 在AVL树中&#xff0c;任一节点对应的两棵子树的最大高度差为1&…

大一新生HTML期末作业 个人网页王嘉尔明星介绍网页设计与制作

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

领悟《信号与系统》之 信号与系统的描述-上节

信号与系统的描述-上节一、信号分类1. 一维信号和多维信号2. 确定信号和随机信号3. 连续时间信号和离散时间信号4. 周期信号和非周期信号5. 能量信号和功率信号二、常见工程信号1. 正弦信号2. 指数信号3. 取样信号4. 单位矩形脉冲信号5. 符号函数在真实的物理世界中&#xff0c…

Redis的优惠券秒杀问题(五)全局唯一ID 以及 秒杀下单

Redis的优惠券秒杀问题&#xff08;五&#xff09;全局唯一ID 以及 秒杀下单 关于优惠秒杀问题的Redis实现章节总览 全局唯一ID 场景分析 不能用自增的原因 id的规律性太明显 受单表数据量的限制 全局唯一ID的条件 全局唯一ID的Redis实现 代码实现 单元测试 其它…

【FPGA】FPGA实现SPI协议读写FLASH(一)----- M25P16操作概述

文章目录一、FLASH介绍&#xff08;M25P16&#xff09;1、M25P16概述2、SPI模式3、存储结构4、指令集5、时间参数二、M25P16工作原理三、M25P16指令操作1、页编程 (PP)2、扇区擦除和整块擦除 (SE and BE)3、写使能 (WREN)4、读ID&#xff08;RDID&#xff09;5、读状态寄存器&a…

使用c#将aj-report桌面化:1.winform嵌入浏览器

说到底,aj-report是个工具,我想大多数人还是想快速使用它来创建一个可以展示的工具。通过之前的章节,你应该可以制作自己的报表页面了,下面我们来看看怎么把aj-report包装成一个桌面能够运行的软件。 当然作为扩展开发,受开源协议限制,我们不能大规模修改aj-report的源代…

【毕业设计】深度学习图像修复算法研究与实现 - python

文章目录1 前言2 什么是图像内容填充修复3 原理分析3.1 第一步&#xff1a;将图像理解为一个概率分布的样本3.2 补全图像3.3 快速生成假图像3.4 生成对抗网络(Generative Adversarial Net, GAN) 的架构3.5 使用G(z)生成伪图像4 在Tensorflow上构建DCGANs5 最后1 前言 &#x1…

PC_OS中断/中断屏蔽字

文章目录程序中断&#x1f383;中断概念中断功能(作用)中断请求中断源中断分类外中断非屏蔽中断和可屏蔽中断陷入(内中断)硬件中断和软件中断关系整理&#x1f388;中断判优&#x1f388;中断优先级CPU响应中断的条件外中断实现思路&#x1f388;中断隐指令 及其工作①关中断②…

下一个倒下的是不是Genesis

今日&#xff0c;一个关于“Genesis今晚破产”的传言在各个社交平台传播&#xff0c;包括行业的KOL也在讨论这个事情&#xff0c;认为Genesis或存在偿付能力问题&#xff0c;该公司将于美国东部时间11月17日8&#xff1a;00am与债权人通话以解释情况。若消息属实&#xff0c;Ge…

【AGC】flutter之agconnect_crash在ios上崩溃

问题背景 flutter agconnect_crash-1.2.0300 运行在ios平台上&#xff0c;出现了如下这个崩溃 NSInvalidArgumentException: *** [NSJSONSerialization dataWithJSONObject:options:error:]: value parameter is nil 0 CoreFoundation 0x00000001830d005c 0x183037000 62678…

视频讲解vue2基础之渲染v-if/v-show/v-for/v-html

大家好&#xff0c;我是你们的老朋友lqj_本人&#xff0c;最近一周没有更新文章了&#xff0c;是因为最近学校有一些活动比赛&#xff0c;也有一部分原因就是我在录制一些关于前端方面的视频&#xff0c;涉及到的领域主要一前端&#xff0c;比如&#xff1a;H5开发&#xff0c;…

项目经理如何搞懂难缠的客户【静说】

作为乙方的项目经理&#xff0c;是否经常遇见难缠的客户&#xff0c;现环境下&#xff0c;大部分都是甲方强势&#xff0c;乙方弱势&#xff0c;双方处于一种不对等的基础上&#xff0c;项目经理如何生产&#xff0c;成功交付项目呢&#xff1f; 流程机制上如何应对&#xff1…

计算机毕业设计jsp教师课堂教学评价系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 教师课堂教学评价系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c…

智慧公交解决方案-最新全套文件

智慧公交解决方案-最新全套文件一、建设背景二、思路架构三、建设方案3大能力&#xff1a;1、数据驱动的智慧公交全息感知能力2、精细化精准化的公交健康诊断能力3、高品质的公交运营组织能力6大系统&#xff1a;1、公交线网健康诊断系统2、职能部门指挥决策支持系统3、公共出行…