JS高级——模块化学习笔记

一、什么是模块化?

到底什么是模块化、模块化开发呢?

  • 事实上模块化开发最终的目的是将程序划分成一个个小的结构;
  • 这个结构中编写属于自己的逻辑代码,有自己的作用域,不会影响到其他的结构;
  • 这个结构可以将自己希望暴露的变量、函数、对象等导出给其结构使用;
  • 也可以通过某种方式,导入另外结构中的变量、函数、对象等;

上面说提到的结构,就是模块;按照这种结构划分开发程序的过程,就是模块化开发的过程;

二、没有模块化带来的问题

早期没有模块化带来了很多的问题:比如命名冲突的问题

当然,我们有办法可以解决上面的问题:立即函数调用表达式(IIFE)

  • IIFE (Immediately Invoked Function Expression)
    在这里插入图片描述

但是,我们其实带来了新的问题:

  • 第一,我必须记得每一个模块中返回对象的命名,才能在其他模块使用过程中正确的使用;
  • 第二,代码写起来混乱不堪,每个文件中的代码都需要包裹在一个匿名函数中来编写
  • 第三,在没有合适的规范情况下,每个人、每个公司都可能会任意命名、甚至出现模块名称相同的情况;

所以,我们会发现,虽然实现了模块化,但是我们的实现过于简单,并且是没有规范的。

  • 我们需要制定一定的规范来约束每个人都按照这个规范去编写模块化的代码;
  • 这个规范中应该包括核心功能:模块本身可以导出暴露的属性,模块又可以导入自己需要的属性;
  • JavaScript社区为了解决上面的问题,涌现出一系列好用的规范,接下来我们就学习具有代表性的一些规范。

三、CommonJS规范和Node关系

CommonJS是一个规范,最初提出来是在浏览器以外的地方使用,并且当时被命名为ServerJS,后来为了体现它的广泛性,修改为CommonJS,平时我们也会简称为CJS。

  • Node是CommonJS在服务器端一个具有代表性的实现;
  • Browserify是CommonJS在浏览器中的一种实现;
  • webpack打包工具具备对CommonJS的支持和转换;

所以,Node中对CommonJS进行了支持和实现,让我们在开发node的过程中可以方便的进行模块化开发:

  • 在Node中每一个js文件都是一个单独的模块;
  • 这个模块中包括CommonJS规范的核心变量:exports、module.exports、require
  • 我们可以使用这些变量来方便的进行模块化开发;

前面我们提到过模块化的核心是导出和导入,Node中对其进行了实现:

  • exports和module.exports可以负责对模块中的内容进行导出
  • require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容

四、exports导出

注意:exports是一个对象,我们可以在这个对象中添加很多个属性,添加的属性会导出;
在这里插入图片描述
上面的代码意味着:

  • main中的why变量等于exports对象
  • 也就是require通过各种查找方式,最终找到了exports这个对象;
  • 并且将这个exports对象赋值给了why变量;
  • why变量就是exports对象了;
    在这里插入图片描述

五、module.exports

但是Node中我们经常导出东西的时候,又是通过module.exports导出的,module.exports和exports有什么关系或者区别呢?

我们追根溯源,通过维基百科中对CommonJS规范的解析:

  • CommonJS中是没有module.exports的概念的;
  • 但是为了实现模块的导出,Node中使用的是Module的类,每一个模块都是Module的一个实例,也就是module;
  • 所以在Node中真正用于导出的其实根本不是exports,而是module.exports
  • 因为module才是导出的真正实现者;
    在这里插入图片描述

但是,为什么exports也可以导出呢?

  • 这是因为module对象的exports属性是exports对象的一个引用
    在这里插入图片描述
module.exports = {};
exports = module.exports;
  • 也就是说 module.exports = exports = main中的why;

六、require细节

我们现在已经知道,require是一个函数,可以帮助我们引入一个文件(模块)中导出的对象。那么,require的查找规则是怎么样的呢?

https://nodejs.org/dist/latest-v14.x/docs/api/modules.html#modules_all_together

这里总结比较常见的查找规则:导入格式如下:require(X)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、模块的加载过程

结论一:模块在被第一次引入时,模块中的js代码会被运行一次

结论二:模块被多次引入时,会缓存,最终只加载(运行)一次

  • 为什么只会加载运行一次呢?
  • 这是因为每个模块对象module都有一个属性:loaded。
  • 为false表示还没有加载,为true表示已经加载;

结论三:如果有循环引入,那么加载顺序是什么?
如果出现下图模块的引用关系,那么加载顺序是什么呢?
在这里插入图片描述

  • 这个其实是一种数据结构:图结构;
  • 图结构在遍历的过程中,有深度优先搜索(DFS, depth first search)和广度优先搜索(BFS, breadth first search);
  • Node采用的是深度优先算法:main -> aaa -> ccc -> ddd -> eee ->bbb

八、CommonJS规范缺点

CommonJS加载模块是同步的:

  • 同步的意味着只有等到对应的模块加载完毕,当前模块中的内容才能被运行;
  • 这个在服务器不会有什么问题,因为服务器加载的js文件都是本地文件,加载速度非常快;

如果将它应用于浏览器呢?

  • 浏览器加载js文件需要先从服务器将文件下载下来,之后再加载运行;
  • 那么采用同步的就意味着后续的js代码都无法正常运行,即使是一些简单的DOM操作;

所以在浏览器中,我们通常不使用CommonJS规范

  • 当然在webpack中使用CommonJS是另外一回事;
  • 因为它会将我们的代码转成浏览器可以直接执行的代码;

在早期为了可以在浏览器中使用模块化,通常会采用AMD或CMD:

  • 但是目前一方面现代的浏览器已经支持ES Modules,另一方面借助于webpack等工具可以实现对CommonJS或者ES Module代码的转换;
  • AMD和CMD已经使用非常少了,所以这里我们进行简单的演练;

AMD主要是应用于浏览器的一种模块化规范:

  • AMD是Asynchronous Module Definition(异步模块定义)的缩写;
  • 它采用的是异步加载模块
  • 事实上AMD的规范还要早于CommonJS,但是CommonJS目前依然在被使用,而AMD使用的较少了;

规范只是定义代码的应该如何去编写,只有有了具体的实现才能被应用:

  • AMD实现的比较常用的库是require.js和curl.js;
    在这里插入图片描述

CMD规范也是应用于浏览器的一种模块化规范:

  • CMD 是Common Module Definition(通用模块定义)的缩写;
  • 它也采用了异步加载模块,但是它将CommonJS的优点吸收了过来;
  • 但是目前CMD使用也非常少了;

CMD也有自己比较优秀的实现方案: SeaJS
在这里插入图片描述

九、认识 ES Module

ES Module和CommonJS的模块化有一些不同之处:

  • 一方面它使用了import和export关键字;
  • 另一方面它采用编译期的静态分析,并且也加入了动态引用的方式

ES Module模块采用export和import关键字来实现模块化:

  • export负责将模块内的内容导出;
  • import负责从其他模块导入内容;

了解:采用ES Module将自动采用严格模式:use strict

十、exports关键字

export关键字将一个模块中的变量、函数、类等导出;

我们希望将其他中内容全部导出,它可以有如下的方式:

  • 方式一:在语句声明的前面直接加上export关键字
    在这里插入图片描述
  • 方式二:将所有需要导出的标识符,放到export后面的 {}中
    注意:这里的 {}里面不是ES6的对象字面量的增强写法,{}也不是表示一个对象的;
    所以: export {name: name},是错误的写法;

在这里插入图片描述

  • 方式三:导出时给标识符起一个别名
    在这里插入图片描述

十一、import关键字

import关键字负责从另外一个模块中导入内容

导入内容的方式也有多种:

方式一:import {标识符列表} from ‘模块’;

  • 注意:这里的{}也不是一个对象,里面只是存放导入的标识符列表内容;
    在这里插入图片描述

方式二:导入时给标识符起别名

在这里插入图片描述

方式三:通过 * 将模块功能放到一个模块功能对象(a module object)上
在这里插入图片描述

十二、export和import结合使用

补充:export和import可以结合使用
在这里插入图片描述

为什么要这样做呢?

  • 在开发和封装一个功能库时,通常我们希望将暴露的所有接口放到一个文件中;
  • 这样方便指定统一的接口规范,也方便阅读;
  • 这个时候,我们就可以使用export和import结合使用;

十三、default用法

前面我们学习的导出功能都是有名字的导出(named exports):

  • 在导出export时指定了名字;
  • 在导入import时需要知道具体的名字;

还有一种导出叫做默认导出(default export)

  • 默认导出export时可以不需要指定名字;
  • 在导入时不需要使用 {},并且可以自己来指定名字;
  • 它也方便我们和现有的CommonJS等规范相互操作;
    在这里插入图片描述

注意:在一个模块中,只能有一个默认导出(default export);

十四、import函数

通过import加载一个模块,是不可以在其放到逻辑代码中的,比如:

为什么会出现这个情况呢?

  • 这是因为ES Module在被JS引擎解析时,就必须知道它的依赖关系;
  • 由于这个时候js代码没有任何的运行,所以无法在进行类似于if判断中根据代码的执行情况;
  • 甚至下面的这种写法也是错误的:因为我们必须到运行时能确定path的值;
    在这里插入图片描述

但是某些情况下,我们确确实实希望动态的来加载某一个模块:

  • 如果根据不同的条件,动态来选择加载模块的路径;
  • 这个时候我们需要使用 import() 函数来动态加载;
    在这里插入图片描述
    import.meta是一个给JavaScript模块暴露特定上下文的元数据属性的对象。
  • 它包含了这个模块的信息,比如说这个模块的URL;
  • 在ES11(ES2020)中新增的特性;
    在这里插入图片描述

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

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

相关文章

JS高级——JSON、数据存储学习笔记

在目前的开发中,JSON是一种非常重要的数据格式,它并不是编程语言,而是一种可以在服务器和客户端之间传输的数据格式。 JSON的全称是JavaScript Object Notation(JavaScript对象符号): JSON是由Douglas Cro…

beautifulsoup获取属性_Python爬虫常用模块:BeautifulSoup

BeautifulSoup用途 BeautifulSoup 借助网页的结构和属性等特性来解析网页,可以用它来方便地从网页中提取所需信息。 BeautifulSoup自动将输入文档转换为Unicode编码,输出文档转换为UTF-8编码。BeautifulSoup依赖于解析器 它除了支持Python标准库中的HTML…

CSS3选择器的研究

属性选择器 [title]:选择带有title属性的元素 [titlehello]:选择属性是title并且值是hello的元素 [title~hello]:选择属性是title并且部分值是hello的元素,hello需要是单独的值,以空格分开 [title*hello]:选择属性是title并且其中包含了hello的元素 [tit…

手写实现简单的Vue事件总线

一、什么是事件总线 自定义事件总线属于一种观察者模式,其中包括三个角色: 发布者(Publisher):发出事件(Event);订阅者(Subscriber):订阅事件&a…

手写实现深拷贝函数

对象相互赋值的一些关系,分别包括: 引入的赋值:指向同一个对象,相互之间会影响;对象的浅拷贝:只是浅层的拷贝,内部引入对象时,依然会相互影响;对象的深拷贝:两…

第一款支持容器和云部署的开源数据库Neo4j 3.0

导读Neo4j 3.0.0 正式发布,这是 Neo4j 3.0 系列的第一个版本。此版本对内部架构进行了全新的设计;提供给开发者更强大的生产力;提供更广阔的部署选择。Neo4j 3.0 被认为是世界上最具伸缩性的基于Java的图片数据库。Neo4j 3.0.0 主要的新特性&…

手写防抖和节流函数

一、认识防抖debounce函数 我们用一副图来理解一下它的过程: 当事件触发时,相应的函数并不会立即触发,而是会等待一定的时间;当事件密集触发时,函数的触发会被频繁的推迟;只有等待了一段时间也没有事件触…

中webgl解析json_WebGL蒙皮(下)

今天继续学习webgl一个重要功能:skinning(蒙皮),内容来自学习网站webglfundamentals,这里仅供学习交流,原文链接:https://webglfundamentals.org/webgl/lessons/zh_cn/webgl-skinning.html。文章并非原创!如…

Vue权限控制——动态注册路由

需求:实现后台管理系统不同用户的权限控制 根据登录的用户的角色动态展示后台管理系统的左侧菜单栏的菜单列表内容,然后还要动态注册对应子菜单的路由 菜单列表内容应该通过后端接口返回: sort为1表示当前项有子菜单sort为2表示当前项没有子…

react不同环境不同配置angular_前端问题集:vue配置环境-给不同的环境配不同的打包命令...

通过vue-cli脚手架构建出一个前端项目,通过npm run build打包,发布到线上,但是这样做需要每次都手动修改接口地址。我们可以通过自行配置打包命令实现无需修改接口地址,打各个环境的包。文档结构大致如下图:1.找到conf…

基于Element-plus封装配置化表单组件(组件的v-model实现)

一、预备知识 1.1 组件的v-model 前面我们在input中可以使用v-model来完成双向绑定: 这个时候往往会非常方便,因为v-model默认帮助我们完成了两件事;v-bind:value的数据绑定 和 input的事件监听; 如果我们现在封装了一个组件…

Scala IDE for Eclipse的下载、安装和WordCount的初步使用(本地模式和集群模式)

不多说,直接上干货! 这篇博客是, 是在Scala IDEA for Eclipse里maven创建scala和java代码编写环境。 Scala IDEA for Eclipse里用maven来创建scala和java项目代码环境(图文详解) 本博文包括: Scala IDE fo…

笔记本AutoCAD启动时闪退怎么办_戴尔笔记本电脑开不了机如何解决【解决方法】...

生活在互联时代下,我们对笔记本的需求是无处不在的,不管是上班族还是学生党,使用笔记本办公和学习给我们的生活带来很大的便捷。但使用的过程中,总有可能会遇到无法预料的问题。比方说 笔记本电脑 无法开机的问题,当…

JS高级——函数执行、作用域链内存结构图

一、JavaScript的执行过程 假如我们有下面一段代码,它在JavaScript中是如何被执行的呢? 1.1 第一步:初始化全局对象 js引擎会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO&#xff09…

JS高级——内存管理和闭包

0、预备知识 0.1 认识内存管理 不管什么样的编程语言,在代码的执行过程中都是需要给它分配内存的,不同的是某些编程语言需要我们自己手动的管理内存,某些编程语言会可以自动帮助我们管理内存: 不管以什么样的方式来管理内存&…

提取多个字段_【博客翻译】建筑物轮廓线提取以及损坏分类

原文链接原作者:Rohit Singh, Sandeep Kumar贡献者:Vinay Viswambharan, Divyansh Jha, Shivani Pathak, Daniel Wilson.翻译:荆雪涵在今年的 Esri 用户大会上,USAA 展示了基于 ArcGIS 深度学习能力,对 Woolsey 火灾进…

读取外部配置文件_SpringBoot外部配置、优先级及配置详解

一、外部配置及优先级SpringBoot的外部配置属性值官方给出了很多种方式,以便可以在不同的环境中使用相同的代码。其使用了非常特别的PropertySource命令,旨在允许合理的覆盖值。当然,如果属性值不同,则这些配置方式中的属性值都会…

Jquery 禁用浏览器的 后退和前进按钮

使用js,Jquery 禁用浏览器的back 和 next 按钮: 有时为了防治用户乱了访问顺序,不得不禁掉浏览器的前进后退按钮。 jQuery(document).ready(function () {if (window.history && window.history.pushState) {$(window).on(popstate, function ()…

JS数据结构与算法——冒泡排序(把大的数字依次往后放)

一、图解排序过程 注意:比较次数和交换次数之所以不一致,是因为:比较了并不一定就需要交换两个数字的位置,比如比较 1 和 2两个数字,由于 后者本身就比前者大,所以不需要交换两者的位置。 二、代码实现 三…

手机长曝光怎么设置_摄影教程丨手机如何拍摄长曝光照片,流光快门,星空银河搞起来!...

微信搜一搜定格取景框长曝光摄影可以拍摄出一些很酷的照片。这是一种非常灵活的摄影技术。它可以用来拍摄城市夜景,记录光绘,也可以拍摄水景片。甚至可以拍摄银河或捕捉星轨。其实长曝光不仅仅适合专业摄影师!任何人都可以用手机进行慢门拍摄…