1.模块
1.1 什么是模块?什么是模块化?
玩过FPS游戏的朋友应该知道,一把装配完整的M4步枪,一般是枪身+消音器+倍镜+握把+枪托
。
如果把M4步枪看成是一个页面的话,那么我们可以做如下类比枪身 -> 61b85035edf2b42260fdb5632dc5728a07ebbc2b3735b6cb0330715d08d2749e
消音器 -> 1aa9e5d373740b65a0cc8f0a02150c53ab946e7546ab66a280dd9c9f9310ecd5
倍镜 -> c787b9a589a3ece771e842a6176cf8e944f9630a3d507ae7532760da37622b0f
握把 -> 15221ee8cba27fc1d7a26c47a001eb9bb68cffaf0006380b7e39ea0c3d532826
枪托 -> c37f8231a37e88427e62669260f0074d84122da5b51c58ef54d7045814144010
OK,你刚才做了一件事情,就是把m4步枪拆成了五个部分,你拆分的每一个部分就是一个模块【module】,你拆分的这个过程就是模块化【modularization】。
模块化是一种编程思想,其核心就是拆分任务,把复杂问题简单化,这样一来既方便多人分工协作,又可以帮助我们迅速定位问题
方便多人分工协作 —— 可以不同的人开发不同的模块,再组合,大大增加团队效率
帮助我们迅速定位问题 —— 后坐力太大,那八成是枪托或握把的问题;声音过大,那八成是消音器的问题。
1.2 模块化的血泪史
下面用一个小栗子讲一讲模块化的发展史
龚先生和棚先生一起接了一个项目,他们俩需要分别实现一些功能,很简单,就是Console出来自己的变量a
于是他们俩一合计,安排龚先生的代码单独放在script1.js
里写,棚先生的代码单独放在script2.js
里写,然后用script标签分别引入
// script1.js文件 var a = 1 console.log(a)
// script2.js文件 var a = 2 console.log(a)
<!--HTML文件--> <script src="./script1.js"></script> <script src="./script2.js"></script>
很快他们遇到了第一个问题 —— 变量命名冲突
尤其是包含了异步的时候,会出现如下情况
// script1.js文件 var a = 1 setTimeout(()=>{ console.log(a) // 我们想console出来1,却console出了2 },1000)
// script2.js文件 var a = 2 console.log(a)
上面的问题明显是由于a是一个全局变量导致的,所以解决思路也很明确——造一个局部变量呗
局部变量
ES5时代使用立即执行函数制造局部变量
// script1.js文件 !function(){ var a = 1 setTimeout(()=>{ console.log(a) // 这下是2了 },1000) }() // 下面有5000行代码
// script2.js文件 console.log(2)
ES6时代直接使用块级作用域+let
// script1.js文件 { let a = 1 setTimeout(()=>{ console.log(a) // 这下是2了 },1000) }
// script2.js文件 { let a = 2 console.log(a) }
通过window连接各个模块
后来公司招了一个前端大佬,说现在只能由他来控制什么时候console变量,于是他新建了一个control.js
文件
并通过window对象连接script1.js和scirpt2.js
// script1.js文件 { let a = 1 window.module1 = function() { console.log(a) } }
// script2.js文件 { let a = 2 window.module2 = function() { console.log(a) } }
// control.js文件 setTimeout(()=>{ window.module1() },1000) window.module2()
这个时候,非常重要的一点就是window是一个全局变量并且充当了一个公用仓库,这个仓库有两个关键作用,存【导出】
和取【依赖】
// script1.js文件 { let a = 1 // 把这个函数存放进window,就是导出到window window.module1 = function() { console.log(a) } }
// control.js文件 setTimeout(()=>{ // 我们从window里取出module1函数进行调用,就是依赖了script1.js文件 window.module1() },1000) window.module2()
依赖加载的顺序
烦人的产品对需求又进行了更改,给了一个name.js文件
// name.js文件 window.names = ['gongxiansheng','pengxiansheng']
要求现在龚先生和棚先生需要Console出自己的名字
这还不简单?几秒钟写好
// script1.js文件 { window.module1 = function() { console.log(window.names[0]) } }
// script2.js文件 { window.module2 = function() { console.log(window.names[1]) } }
// control.js文件 setTimeout(()=>{ window.module1() },1000) window.module2()
<!--HTML文件--> <script src="./script1.js"></script> <script src="./script2.js"></script>
但很快他们发现,console出来的都是undefined
前端大佬一眼看出了问题,对他们俩说你们依赖的代码一定要在你们自己的代码前引入,不然是取不到值的;你看我的control.js是不是在你们俩的代码后面引入的,因为我用到了你们俩的代码了呀
噢噢,原来是js文件加载顺序问题,改一下吧
<!--HTML文件--> <script src="./name.js"></script> <script src="./script1.js"></script> <script src="./script2.js"></script> <script src="./control.js"></script>
但是在人多了以后,我们到时候会搞不清楚到底谁依赖了谁,保险起见只能全部都加载,性能浪费了太多
,前端大佬摇头叹息道
2. ES6的模块
2.1 ES6之前模块化的痛点
变量冲突
要用window连接各个模块
依赖需要全部加载
还要TMD注意加载顺序
模块化是ES6的最大的亮点之一,因为在ES6之前的语法里从未有过模块化的体系,这对开发大型的、复杂的项目形成了巨大障碍。因为我们无法对项目进行拆分,无法更好地进行多人协作开发。更重要的是,其它大部分语言都支持模块化。
既然语言不支持,那么如何将模块化引入JS呢?
前端社区就自己制定了一些模块加载方案——这也是CommonJS【服务器】和AMD、CMD【浏览器】的由来。
但是现在ES6引入了模块化的功能,实现起来非常简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
2.2 import和export的用法
import和export语法较为简单,大家去MDN可以看非常详细的讲解,笔者在这里知识用注释简单介绍一下
export语法
// 命名导出 export { name1, name2, …, nameN }; export { variable1 as name1, variable2 as name2, …, nameN }; export let name1, name2, …, nameN; // also var export let name1 = …, name2 = …, …, nameN; // also var, const export function FunctionName() {...} export class ClassName {...} // 默认导出 export default expression; export default function (…) { … } // also class, function* export default function name1(…) { … } // also class, function* export { name1 as default, … }; // 将其它模块内的导出作为当前文件的导出 export * from …; export { name1, name2, …, nameN } from …; export { import1 as name1, import2 as name2, …, nameN } from …;
import用法
import defaultExport from "module-name"; // 导入默认默认变量 import * as name from "module-name"; // 将模块内所有变量导出,并挂载到name下【name是一个module对象】。什么要有as——为了防止export出来的变量命名冲突 import { export } from "module-name"; // 导入某一个变量 import { export as alias } from "module-name"; // 导入某一个变量并重命名 import { export1 , export2 } from "module-name"; // 导入两个变量 import { export1 , export2 as alias2 , [...] } from "module-name"; // 导入多个变量,同时可以给导入的变量重命名 import defaultExport, { export [ , [...] ] } from "module-name"; // 导入默认变量和多个其它变量 import defaultExport, * as name from "module-name"; // 导入默认变量并重新命名 import "module-name"; // 导入并加载该文件【注意文件内的变量必须要通过export才能被使用】 var promise = import(module-name); // 异步的导入
使用import和export改写第一节的代码
// name.js文件 let names = ['gongxiansheng','pengxiansheng'] export default names
// script1.js import names from './name.js' let module1 = function () { console.log(names[0]) } export default module1
// script2.js import names from './name.js' let module2 = function() { console.log(names[1]) } export default module2
// control.js import module1 from './script1.js' import module2 from './script2.js' setTimeout(() => { module1() }, 1000) module2()
<!--HTML文件--> <script type="module" src="./control.js"></script> <!--注意一定要加上type="module",这样才会将这个script内的代码当做模块来对待-->
2.3 拓展:import和export的一些运行原理
2.3.1 ES6 模块输出的是值的引用,输出接口会动态绑定
其实就是按照数据类型里的引用类型
的概念去理解。
这一点与 CommonJS 规范完全不同。
CommonJS 模块输出的是值的缓存
,不存在动态更新。
// module1.js export var foo = 'bar'; setTimeout(() => foo = 'baz', 500);
// module2.js import {foo} from './module1.js' console.log(foo) setTimeout(() => console.log(foo), 1000); // console的结果 // bar // baz
2.3.2 export可以出现在模块内的任何位置,但不能处于块级作用域内
// 报错 { export let foo = 'bar'; }
2.3.3 import具有提升效果(类似于var),会提升到整个模块的头部,首先执行
console.log(foo) import {foo} from './script1.js'
参考资料:ECMAScript 6 入门
本文纯属原创,为了方便大家理解,小故事,小栗子都是笔者自己想的。如果您觉得对你有帮助,麻烦给个赞,给作者灰暗的生活挥洒挥洒积极向上的正能量,谢谢啦^_^。
相关推荐:
以上是什么是模块?深刻理解ES6模块的详细内容。更多信息请关注PHP中文网其他相关文章!

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。

C 和JavaScript通过WebAssembly实现互操作性。1)C 代码编译成WebAssembly模块,引入到JavaScript环境中,增强计算能力。2)在游戏开发中,C 处理物理引擎和图形渲染,JavaScript负责游戏逻辑和用户界面。

JavaScript在网站、移动应用、桌面应用和服务器端编程中均有广泛应用。1)在网站开发中,JavaScript与HTML、CSS一起操作DOM,实现动态效果,并支持如jQuery、React等框架。2)通过ReactNative和Ionic,JavaScript用于开发跨平台移动应用。3)Electron框架使JavaScript能构建桌面应用。4)Node.js让JavaScript在服务器端运行,支持高并发请求。

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。