搜索
首页web前端js教程为什么需要模块化?js中常用模块化方案介绍

为什么需要模块化?js中常用模块化方案介绍

Oct 26, 2018 pm 03:20 PM
es6javascript模块化

本篇文章给大家带来的内容是关于为什么需要模块化?js中常用模块化方案介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

为什么需要模块化

在ES6出现之前,JS语言本身并没有提供模块化能力,这为开发带来了一些问题,其中最重要的两个问题应当是全局污染和依赖管理混乱。

// file a.js
var name = 'aaa';
var sayName = function() {
    console.log(name);
};
<!-- file index.html -->
<script src=&#39;xxx/xxx/a.js&#39;></script>

<script>
    sayName(); // 'aaa'
    
    // code...
    
    var name = 'bbb';
    
    sayName(); // 'bbb'
</script>

上面的代码中,我们两次调用a.js所提供的sayName函数输出了不同结果,很明显这是因为两个文件都对变量name进行了赋值,因此相互之间造成了影响。当然我们可以在编写代码时注意不要定义已存在的变量名,但是当一个页面引用了10几个几百行的文件时,记住所有已经定义过的变量显然不太现实。

// file a.js
var name = getName();
var sayName = function() {
    console.log(name)
};
// file b.js
var getName = function() {
    return 'timo';
};
<script src=&#39;xxx/xxx/b.js&#39;></script>
<script src=&#39;xxx/xxx/a.js&#39;></script>

<script>
    sayName(); // 'timo'
</script>
<script src=&#39;xxx/xxx/a.js&#39;></script>
<script src=&#39;xxx/xxx/b.js&#39;></script>

// Uncaught ReferenceError: getName is not defined

上面的代码说明,多个文件有依赖关系时,我们需要确保其引入的顺序,从而保证运行某个文件时,其依赖已经提前加载,可以想象,面对越大型的项目,我们需要处理的依赖关系也就越多,这既麻烦又容易出错。

而为了解决这些,社区中出现了许多为JS语言提供模块化能力的规范,借助这些规范,能让我们的开发更加方便安全。

常见模块化方案

CommonJS

CommonJS是由社区提出的模块化方案中的一种,Node.js遵循了这套方案。

基本写法

// file a.js
var obj = {
    sayHi: function() {
        console.log('I am timo');
    };
};

module.exports obj;
// file b.js
var Obj = require('xxx/xxx/a.js');

Obj.sayHi(); // 'I am timo'

上面的代码中,文件a.js是模块的提供方,文件b.js是模块调用方。

规范

  1. 每个文件都是一个模块;

  2. 在模块内提供module对象,表示当前模块;

  3. 模块使用exports对外暴露自身的函数/对象/变量等;

  4. 模块内通过require()方法导入其他模块;

CommonJS的规范,简单来说就是上面4条,可以对照基本写法中的例子理解一下,在实际实现中,Node.js虽然遵循CommonJS规范,但是仍然对其进行了一些调整。

AMD

AMD是模块化规范中的一种,RequireJS遵循了这套规范。

基本用法

 // file a.js
 define('module', ['m', './xxx/n.js'], function() {
    // code...
 })

上面的代码中,文件a.js向外导出了模块;

规范

AMD中,暴露模块使用define函数

define(moduleName, [], callback);

如上面代码,define函数共有三个参数

  • moduleName该参数可以省略,表示该模块的名字,一般作用不大

  • ['name1', 'name2'],第二个参数是一个数组,表示当前模块依赖的其他模块,如果没有依赖模块,该参数可以省略

  • callback,第三个参数是必传参数,是一个回调函数,内部是当前模块的相关代码

其他

ADM的特点是依赖前置,这是ADM规范与接下来要介绍的CMD规范最大的不同,依赖前置是指:在运行当前加载模块回调前,会首先将所有依赖包加载完毕,也是就是define函数的第二个参数中指定的依赖包。

CDM

基本写法

 define(function(require, exports, module) {   
    var a = require('./a')  
    a.doSomething();
    // code... 
    var b = require('./b') 
    // code...
})

上面代码是CMD规范导出模块的基本写法;

规范

从写法可以看出,CMD的写法和AMD非常像,其主要区别是对于依赖加载时机的不同,上面已经说过,AMD是依赖前置,而CMD规范推崇就近原则,简单说就是在模块运行前并不加载依赖,模块运行过程中,当需要某个依赖时,再去进行加载。

UMD

CommonJS、AMD、CMD并行的状态下,就需要一种方案能够兼容他们,这样我们在开发时,就不需要再去考虑依赖模块所遵循的规范了,而UMD的出现就是为了解决这个问题。

基本写法

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //Node, CommonJS之类的
        module.exports = factory(require('jquery'));
    } else {
        //浏览器全局变量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //方法
    function myFunc(){};
    //暴露公共方法
    return myFunc;
}));

上面的代码是UMD的基本写法,从代码就可以看出,其能够同时支持CommonJS规范和AMD规范。

ES6 module

上面分别介绍了CommonJS、AMD、CMD和UMD,他们都是社区对于JS实现模块化的贡献,这个规范其产生的根本原因,都是JS语言自身没有模块化能力,而目前,在JS最新的语言规范ES6中,已经为JS增加了模块化能力,而JS自身的模块化方案,完全能够替代目前社区提出的各类规范,且能够做到浏览器端和Node端通用。

ES6中的模块化能力由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

export命令

ES6中一个文件就是一个模块,模块内部的变量/函数等外部是无法访问的,如果希望将内部的函数/变量等对外暴露,供其他模块进行使用,就需要通过export命令进行导出

// file a.js
export let a = 1;
export let b = 2;
export let c = 3;
// file b.js
let a = 1;
let b = 2;
let c = 3;

export {a, b, c}
// file c.js
export let add = (a, b) => {
    return a + b;
};

上面三个文件的代码,都是通过export命令导出模块内容的示例,其中a.js文件和b.js文件都是导出模块中的变量,作用完全一致但写法不同,一般我们更推荐b.js文件中的写法,原因是这种写法能够在文件最底部清楚地知道当前模块都导出了哪些变量。

import命令

模块通过export命令导出变量/函数等,是为了让其他模块能够导入去使用,在ES6中,文件导入其他模块是通过import命令进行的

// file d.js
import {a, b, c} from './a.js';

上面的代码中,我们引入了a.js文件中的变量a、b、c,import在引入其他模块内的函数/变量时,必须与原模块所暴露出来的函数名/变量名一一对应。
同时,import命令引入的值是只读的,如果尝试对其进行修改,则会报错

import {a} d from './a.js';
a = 2; // Syntax Error : 'a' is read-only;

export default命令

从上面import的介绍可以看到,当需要引入其他模块时,需要知道此模块暴露出的变量名/函数名才可以,这显然有些麻烦,因此ES6还提供了一个import default命令

// file a.js

let add = (a, b) => {
    return a+b
};
export default add;
// file b.js
import Add from './a.js';

Add(1, 2); // 3

上面的代码中,a.js通过export default命令导出了add函数,在b.js文件中引入时,可以随意指定其名称

export default命令是默认导出的意思,既然是默认导出,显然只能有一个,因此每个模块只能执行一次export default命令,其本质是导出了一个名为default的变量或函数。

以上是为什么需要模块化?js中常用模块化方案介绍的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault。如有侵权,请联系admin@php.cn删除
JavaScript的角色:使网络交互和动态JavaScript的角色:使网络交互和动态Apr 24, 2025 am 12:12 AM

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

C和JavaScript:连接解释C和JavaScript:连接解释Apr 23, 2025 am 12:07 AM

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

从网站到应用程序:JavaScript的不同应用从网站到应用程序:JavaScript的不同应用Apr 22, 2025 am 12:02 AM

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

Python vs. JavaScript:比较用例和应用程序Python vs. JavaScript:比较用例和应用程序Apr 21, 2025 am 12:01 AM

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

C/C在JavaScript口译员和编译器中的作用C/C在JavaScript口译员和编译器中的作用Apr 20, 2025 am 12:01 AM

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

JavaScript在行动中:现实世界中的示例和项目JavaScript在行动中:现实世界中的示例和项目Apr 19, 2025 am 12:13 AM

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

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

了解JavaScript引擎:实施详细信息了解JavaScript引擎:实施详细信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

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

热工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。