最近在搞跨平台解决方案,讨论关于模块划分的问题以及如何尽量多的复用逻辑代码。于是就有了此文章,之前的博客也写过,不过由于主机商跑路,宝贵的资源也就没了,说多了都是泪~ 这里按模块化发展的历史回溯的时间序

一. ES6 Moudle

这个是目前前端小伙伴接触的最多的,是浏览器和服务端通用的模块化解决方案,主要命令为:exportimport。export用于导出本模块对外的接口,import用于导入某个模块的功能。

//modulA.js

export var goingta = "goingta";

export function hello() { console.log("hello world"); }

const fn = function() { goingta = "new goingta"; console.log("fn"); };

export { fn };

const come = 1; export default come;

// export default const errorDefault = 2 // default 不能导出变量表达式

//index.js

import come, { fn, hello } from "./moduleA.js";

import * as aModule from "./moduleA.js";

fn();

hello();

console.log("come", come);

console.log("aModule", aModule); //aModule Module{default: 1, fn: ƒ (),…}

console.log("aModule.goingta", aModule.goingta); //new goingta

从上面例子,我们可以看到export可以在任意地方导出变量,方法,并且也可以将已有变量或方法包在一个{}对象里面导出,但是最终都会包在一个{}里面,简单理解就是:

1. 如果单独导出一个变量或方法则是往将要导出{}对象里面添加属性。

2. 如果导出的是{},则和已生成的导出{}对象合并。

然后说一下特例export default,这个是在导出对象里面加一个default属性,还有一点值得注意的是export default后面不能跟变量表达式。

最后还有一个重点是,ES6 Moudle是编译时输出,并且是值引用。

二. CommonJS

CommonJS最主要的代表就是Node.js,主要命令:moduleexportsrequire。其中有个令人疑惑的点是exportsmodule.exports,其实理解起来也很简单,就是在模块里面加了一句: exports = module.exports = {}; exportsmodule.exports指向同一个内存区域,只要在exports加了属性,则module.exports会跟着变化,但是最终导出对外的接口是以module.exports为准,所以不推荐直接使用exports。例如:

//moduleA.js

let goingta = "我是goingta";

exports.goingta = goingta;

exports.fn = function() { goingta = "new goingta"; };

exports = "把exports指向其他区域";

module.exports = "我现在没有goingta了,也没有fn了"; // 这行代码注释掉会有不一样的结果

// index.js

let obj = require("./moduleA.js");

console.log(obj);

最终输出的是:"我现在没有goingta了,也没有fn了",如果把最后一行代码注释掉则输出:{goingta: "我是goingta", fn:ƒ ()}

对于CommonJS规范来说,很重要的一点是CommonJS输出的是一个值拷贝,并且是运行时加载。

把上面的示例代码简化一下就可以看出:

//moduleA.js

let goingta = "我是goingta";

module.exports = { goingta };

module.exports.fn = function() { goingta = "new goingta"; };

//index.js

let obj = require("./moduleA.js");

obj.fn();

console.log("obj.goingta", obj.goingta);

最终结果输出:"我是goingta"

三. ES6 Module和CommonJS的区别

从上面的结论我们不难得出,ES6 ModuleCommonJS的本质区别:

1. 引用方式:CommonJS模块输出是值的拷贝,ES6 Module模块输出的值是引用

2. 时机:CommonJS是运行时加载,ES6 Module是编译是输出

四. 模块化历史

差不多在6年前,当项目越来越大,用JS模拟划分出来的类导致文件越来越多以及需要前置依赖的各种库(那个时代的三叉戟jQueryBackboneUnderscore),模块化以及各种脚手架开始兴起,于是有了AMDCMD以及当年这两种规范之争-AMD推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。AMD的代表是require.jsCMD的代表是玉伯的Sea.js

五. AMD和CMD

AMD规范是采用异步方式,依赖前置必须一开始就写好,所有的依赖加载完成后才会执行回调函数里的内容:

// moduleB.js
//一开始就要写好这个模块所有的依赖
define(["jQuery", "underscore", "moduleA"], function($, _) {     if (false) {
        // 即便没用到moduleA,也会被提前执行
        moduleA.doSomething()
    }
}); `CMD`规范按玉伯大大的原话`"是 Sea.JS 在推广过程中对模块定义的规范化产出"`,并且当时在国内认可度很高。依赖就近书写: // moduleB.js define(function(require, exports, module) {
    var moduleA = require('moduleA.js');//用到时才写     moduleA..doSomething()
    //一堆其他业务代码
    var $ = require('jquery.js');     $.xxxx()
});

六. 更早以前

在07年左右正式有前端开发这个职位后(以前都是后端研发兼写前端代码),SEO、性能优化、语义模板、浏览器兼容、代码混淆加密等等都需要前端开发承接是,往往是一个公用的base.js外加几个业务js放在html里面,然后用deferasync标记:

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

<script src="moduleA.js" defer></script>

deferasync的区别在于:defer是“渲染完再执行”,async是“下载完就执行”。

前端模块化之CommonJS,ES6,AMD,CMD的更多相关文章

  1. js模块化编程之CommonJS和AMD/CMD

    js模块化编程commonjs.AMD/CMD与ES6模块规范 一.CommonJS commonjs的require是运行时同步加载,es6的import是静态分析,是在编译时而不是在代码运行时.C ...

  2. CommonJs/ES6/AMD模块的用法以及区别

    github地址: 一直以来对CommonJs/AMD/CMD/ES6的文件模块加载一直懵懵懂懂.甚至有时会将CommonJs的exports和ES6的export.default搞混.趁着学习web ...

  3. javascript模块化之CommonJS、AMD、CMD、UMD、ES6

    javascript模块化之CommonJS.AMD.CMD.UMD.ES6 一.总结 一句话总结: CommonJS是同步加载模块,用在服务端:AMD是异步加载模块,用于浏览器端 1.为什么服务器端 ...

  4. 前端模块化——彻底搞懂AMD、CMD、ESM和CommonJS

    我们知道,在NodeJS之前,由于没有过于复杂的开发场景,前端是不存在模块化的,后端才有模块化.NodeJS诞生之后,它使用CommonJS的模块化规范.从此,js模块化开始快速发展. 模块化的开发方 ...

  5. JS模块化规范CommonJS,AMD,CMD

    模块化是软件系统的属性,这个系统被分解为一组高内聚,低耦合的模块.理想状态下我们只需要完成自己部分的核心业务逻辑代码,其他方面的依赖可以通过直接加载被人已经写好模块进行使用即可.一个模块化系统所必须的 ...

  6. [转]js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    原文: https://www.cnblogs.com/chenguangliang/p/5856701.html ------------------------------------------ ...

  7. (转) 前端模块化:CommonJS,AMD,CMD,ES6

    模块化的开发方式可以提高代码复用率,方便进行代码的管理.通常一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数.目前流行的js模块化规范有CommonJS.AMD.CMD以及ES6的模块 ...

  8. 模块化(CommonJs、AMD、CMD、UMD)发展历史与优缺点

    全文主要整理自摘自<Webpack中文指南>(好文,建议直接去看,以下仅对该系列文章中的<历史发展>篇幅进行备份——也整理了点其他内容) 模块化 模块化是老生常谈了,这里不做阐 ...

  9. js模块化编程之彻底弄懂CommonJS和AMD/CMD!

    先回答我:为什么模块很重要? 答:因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块.但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写 ...

随机推荐

  1. noip第21课作业

    1. 遍历二叉树 [问题描述] 以先序的方式建立一棵二叉树,空结点用‘#’号表示,例如:abd###ce##f##,将建立一棵如下的二叉树: 输出其中序序列和后序序列,其中总结点个数不超过100. 输 ...

  2. pm2

    使用PM2将Node.js的集群变得更加容易(http://www.cnblogs.com/jaxu/p/5193643.html) nodejs pm2配置使用教程(http://blog.csdn ...

  3. bootstrap3相关文档

    ,每列分配多列 <divclass="container"> <div class="row"> <div class=" ...

  4. scikit-FEM-mesh

    # -*- coding: utf-8 -*- """ “Mesh”模块包含了有限元网格的不同类型. See the following implementations: ...

  5. 10.scrapy入门

    Scrapy 框架 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页 ...

  6. play framework - 初识

    背景 研发代码框架是play-framework框架,想看代码的话,需要学习下play框架.IDE工具的话之前一直用的idea,所以本文涉及的idea play的配置 和 一些play的简单知识 认识 ...

  7. sql解决避免除以零的错误

    在实际项目中,我们可能会遇到求百分比,比值等带除法的sql语句.这时,我们也许会遇到分母为零的情况.下面给出我总结的一些方法: 1. 用NULLIF函数: 首先说一下NULLIF函数的语法: NULL ...

  8. 【NumberValidators】工商营业执照号码和统一社会信用代码验证

    从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商 ...

  9. WinForm中实现Loading加载界面

    1,LoaderForm窗体中添加PictureBox,然后添加Loading图片 2,窗体内属性设置 StartPosition :CenterScreen在屏幕中心显示 TopMost:True置 ...

  10. Java反射机制介绍

    1. 文档概述 Java反射是Java被视为动态(或准动态)语言的一个关键性质,Java反射机制容许程序在运行时加载.探知.使用编译期间完全未知的classes.换言之,Java可以加载一个运行时才得 ...