javascript模块 (Module) 简介

news/2024/12/24 11:32:50/文章来源:https://www.cnblogs.com/chinasoft/p/18531134

https://blog.csdn.net/chehec2010/article/details/119804381

 

   随着ES6的出现,js模块已经成为正式的标准了。曾经为了解决js模块问题而发展起来的民间秘籍,requireJs(AMD)、SeaJs(CMD)、Node(CommonJs),已经或者不久的将来会成为历史。了解历史也是很重要的,因为正式标准就是以民间秘籍为基础而发展起来的,有些规范仍然被广泛应用于开发中(CommonJS)。 

ES6的class是面向对象的语法糖,升级了ES5的构造函数的原型链继承的写法,并没有解决模块化问题。Module功能则是为了解决这一问题而提出的。

在ES6之前,社区制定了一些模块加载方案,最主要的有CommonJS和AMD两种。CommonJS用于服务器,AMD用于浏览器。

ES6模块的设计思想是尽量静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

ES6模块不是对象,而是通过export命令显式指定输出的代码,输入时也采用静态命令的形式。

什么是模块?

一个模块(module)就是一个文件。一个脚本就是一个模块。就这么简单。

模块可以相互加载,并可以使用特殊的指令 export 和 import 来交换功能,从另一个模块调用一个模块的函数:

  • export 关键字标记了可以从当前模块外部访问的变量和函数。
  • import 关键字允许从其他模块导入功能。
import { Fun1, Fun2, Fun3 } from 'file';

以上代码的实质是从file模块加载3个方法Fun1、Fun2和Fun3,其他方法不加载。这种加载方式称为编译时加载,即ES6能在编译时就完成模块编译。

一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果想要外接获取模块内部的某个变量或方法,就必须使用export关键字输出该变量。

  1.  
    // profile.js
  2.  
    export var firstName = "John";
  3.  
    export var lastName = "Jackson";
  4.  
    export var year = 1999;

上述代码表示在profile.js文件(模块)中,输出了3个变量。

这种写法等价于:

  1.  
    var firstName = "John";
  2.  
    var lastName = "Jackson";
  3.  
    var year = 1999;
  4.  
    export { firstName, lastName, year };

在export命令后面使用大括号指定了所要输出的一组变量,等价于在每个变量前面加export。

export命令除了可以输出变量,也可以输出函数和类,写法相同。

export输出的变量就是本来的名字,但是可以使用as关键字重命名。

  1.  
    function f1() {}
  2.  
    function f2() {}
  3.  
    export { v1 as Fun1, v2 as Fun2, v2 as Foo };

可以使用as关键字对同一个变量或方法重命名两次,使其在引入模块中,可以使用不同的名字进行引用。

 

export命令可以出现在模块的任意顶层作用域的位置,不能出现在块级作用域内。

export语句输出的值是动态绑定的,绑定其所在的模块。

import命令

使用export命令定义了模块的对外接口后,其他JS文件就可以通过import命令加载这个模块的接口。

  1.  
    // main.js
  2.  
    import { firstName, lastName, year } from './profile';

import命令接受一个对象,里面指定了要从其他模块导入的变量名。对象中的变量名必须和要加载的模块导出的接口变量名一致(如果接口没有使用as关键字,就使用原始变量名,如果使用as关键字,则使用重命名后的接口名)。

同理,如果要对引入的变量名进行重命名,可以在import命令中使用as关键字,将输入的变量重命名。

  1.  
    // main.js
  2.  
    import { firstName as surname } from './profile';

上述写法中,需要书写每个接口的变量名,如果是要对整个模块进行整体加载,可以使用星号(*)指定一个对象,将输出模块的所有接口都加载到这个对象上。

  1.  
    // main.js
  2.  
    import * as person from './profile';

import命令具有提升效果,会提升到整个模块的顶部首先执行。

export default命令

import命令在加载变量名或函数名时,需要事先知道导出的模块的接口名,否则无法加载。可以使用export default命令指定模块的默认输出接口。

  1.  
    // profile.js
  2.  
    export default function () {
  3.  
    console.log("my name is John Jackson, I was born in 1999");
  4.  
    }

上述代码中,profile模块默认输出的是一个函数。这样,导入模块就可以不用指定要加载的接口名了。

  1.  
    // main.js
  2.  
    import myName from './profile';
  3.  
    myName(); // "my name is John Jackson, I was born in 1999"

在main.js文件中,myName指代的就是profile文件输出的默认接口。这意味着import命令可以用任意名称指向profile文件输出的默认接口,而不需要知道接口名。

 

export default命令用在非匿名函数前也是可以的,此时函数名在模块外部是无效的,加载时视同匿名函数。

  1.  
    // profile.js
  2.  
    export default function sayName () {
  3.  
    console.log("my name is John Jackson, I was born in 1999");
  4.  
    }
  5.  
     
  6.  
    // main.js
  7.  
    import myName from './profile';
  8.  
    myName(); // "my name is John Jackson, I was born in 1999"

一个模块只能有一个默认输出,因此export default在一个模块中只能使用一次。所以,对应的import命令可以不加大括号。

如果要在一条import命令中同时引入默认方法和其他变量,可以写成以下这样:

import customName, { otherMethod } from './module-name';

customName指代默认接口的命名,otherMethod指代其他接口。

模块的继承

模块之间可以继承。假设有个Circle模块继承了Shape模块。

  1.  
    // cicle.js
  2.  
    export * from 'Shape';
  3.  
    export var pi = 3.14159265359;
  4.  
    export default function area(r) {
  5.  
    return pi * r * r;
  6.  
    }

export * 表示输出模块Shape的所有属性和方法,但不会输出Shape的默认方法。

 

module命令

如果要整体加载模块,可以使用module命令代替上述的import * as命令。module命令不会加载模块的默认方法。需要额外使用import命令加载模块的默认方法。

  1.  
    // main.js
  2.  
    module person from './profile';

ES6模块加载的实质

ES6模块输出的是值的引用。

ES6模块遇到模块加载命令import时不会去执行模块,只会生成一个动态的只读引用。等到真的需要用到时,再到模块中取值。

ES6的输入有点像UNIX系统的“符号链接”,原始值变了,输入值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。

  1.  
    // lib.js
  2.  
    export let count = 3;
  3.  
    export function add() { count++; }
  4.  
     
  5.  
    // main.js
  6.  
    import { count, add } from './lib';
  7.  
    console.log(count); // 3
  8.  
    add();
  9.  
    console.log(count); // 4

由于ES6输入的模块变量只是一个“符号链接”,所以这个变量是只读的,对它进行重新赋值会报TypeError异常。

  1.  
    // lib.js
  2.  
    export let obj = {};
  3.  
     
  4.  
    // main.js
  5.  
    import { obj } from './lib';
  6.  
    obj.prop = 123; // OK
  7.  
    obj = {}; // TypeError

obj指向的地址是只读的,无法为其重新赋值。

 

模块接口的导出

 

模块接口的导入

 

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

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

相关文章

11.6虎牙客户端一面

1.自我介绍 2.共享屏幕看代码 ​ 类内不能用auto推导成员变量类型 ​ 类内的成员函数调用应该用作用域 3.struct和class区别 相同点两者都拥有成员函数、公有和私有部分 任何class能完成的工作,struct同样能完成不同点如果不指定,struct默认公有,class默认私有 class默认pri…

helm-v3-新的功能

helm-v3-新的功能 Helm 是什么? Helm 是一个命令行下的客户端工具。主要用于 Kubernetes 应用程序 Chart 的创建、打包、发布以及创建管理本地或者远程的Chart仓库。 Helm 解决什么痛点?如何统一管理、配置和更新分散的k8s yaml资源文件 如何分发和复用一套应用模板 如何将应…

基于Java+SpringBoot心理测评心理测试系统功能实现四

三、部分系统功能心理测试信息数据层Dao、试题题型信息数据层Dao、试题信息数据层Dao、角色信息数据层Dao、用户信息数据层Dao、前台用户信息数据层Dao、咨询师预约信息数据层Dao、咨询师信息数据层Dao、试卷信息数据层Dao、试卷答案信息数据层Dao一、前言介绍: 1.1 项目摘要 …

七、Spring Boot集成Spring Security之前后分离认证最佳实现

前后分离项目认证流程代码实现,基于spring security原生流程设计,实现RESTFUL接口、分布式缓存二、自定义用户名密码认证过滤器RestfulUsernamePasswordAuthenticationFilter 1、注册过滤器方式使用httpSecurity.addFilter/addFilterBefore/addFilterAfter向过滤器链中添加过…

WPF Slider控件 划一划

WPF Slider控件 划一划Slider控件就是常见的滑块。 控件的外观一般显示一系列刻度,并存在一个可以拖动的滑块,可以通过拖动滑块来控制控件的值。如Windows11的音量控制。 做一个简单的滑块控件,并将滑块的值显示在文本框中。<StackPanel Margin="10"><!…

5种AI合同审查方法,免费开源,提升50%法律文件比对效率

一、系统概述 在法律行业,合同和法律文件的版本审查是确保合规与降低风险的重要步骤。然而,手动对比文档各版本间的差异不仅耗时,且易产生误判。思通数科的AI多模态能力平台专为法律文件审核设计,结合了先进的Diff算法与Levenshtein距离算法,支持字符、单词、段落的精确对…

Markdown编辑入门

Markdown编辑入门 标题 三级标题 四级标题 字体 Hello,world Hello,world Hello,world ~~Hello,world ~~ 引用十步杀一人,千里不留行。分割线图片列表ABC123链接 百度 表格姓名 年龄 性别张三 18 男代码 <html>

基于Azure DevOps 的 CICD 项目部署(.Net Core)

使用微软的 来进行CICD 链接:https://dev.azure.com 创建新项目3.创建项目名称4.选择仓库地址5.选择空模板6.创建代理池7.按照以下步骤把代理部署到服务器上8.连接你的服务器 9.创建新的文件夹 mkdir myange cd myagent 10.可通过链接下载文件 wget https://vstsagentpackage.…

2个月搞定计算机二级C语言——真题(9)解析

1. 前言 本篇我们讲解2个月搞定计算机二级C语言——真题92. 程序填空题 2.1 题目要求2.2 提供的代码 #include <stdio.h> double f1(double x) {return x * x; } double f2(double x, double y) {return x * y; } /**********found**********/ __1__ fun(int i, do…

【转载】TortoiseSVN怎么恢复到以前版本-恢复到以前版本的方法

原文链接:https://blog.csdn.net/hbiao68/article/details/131595214 SVN(Subversion)是一个版本控制系统,它允许用户跟踪文件的更改并回退到以前的版本。 第一步:进到到文件目录,右键点击【空白处】。 第二步:点击打开【TortoiseSVN】。 第三步:点击【更新至版本】。 …

如何在windows中安装达梦数据库?

前言 近年来,国产数据库越来越流行了,其中的原因大家也都知道。其中,我接触过的一款数据库就是达梦数据库。这个数据库的使用还是挺方便的。我知道最近有越来越多的小伙伴要开始国产化改造了,所以,对于达梦数据库这样的国产数据库,肯定想要了解很多知识的。所以,今天就来…

基于GA-PSO-SVM算法的混沌背景下微弱信号检测matlab仿真

1.算法运行效果图预览 (完整程序运行后无水印)svm参数取值对检测性能的影响: SVM,PSO,GA-PSO-SVM的检测性能对比: 2.算法运行软件版本 matlab2022a3.部分核心程序 (完整版代码包含详细中文注释和操作步骤视频,参考文献,说明文档)load GAPSO.mat %调用四个最优的参数 ta…