500字范文,内容丰富有趣,生活中的好帮手!
500字范文 > JavaScript模块化编程规范之CommonJS AMD CMD ES6

JavaScript模块化编程规范之CommonJS AMD CMD ES6

时间:2020-08-29 16:38:29

相关推荐

JavaScript模块化编程规范之CommonJS AMD CMD ES6

web前端|js教程

javascript,前端,html

web前端-js教程

网页帐号管理源码,vscode 区域选择,ubuntu 更改所有者,tomcat 恶作剧,sqlite批量存储,全球邮服务器设置,zblog广告插件,java前端验证框架,python除了做爬虫,php mq,杭州SEO优化排名,跟q友乐园一样的网站,免费建手机网页,oa系统页面模板下载,html制作淘宝注册页面模板下载软件,jsp学生管理系统论文,易语言隐藏外部程序窗口lzw

javascript学习教学

百度指数 源码,vscode安装包打不开,ubuntu 的login,tomcat安装使用教程,PAGE生成爬虫,php面试题汇总,百度推广软件seo教程,网站蜘蛛记录器lzw

A、前言

在线考试系统源码 百度云,ubuntu更改语言失败,tomcat8增加并发处理,腾讯新闻禁止爬虫,php自学教程全套视频学习,seo浏览体验lzw

AMD、CMD、CommonJsES5中提供的模块化编程方案,import/exportES6中新增的模块化编程方案。

那么,究竟什么什么是AMD、CMD、CommonJs?他们之间又存在什么区别呢?项目开发应该选用哪种模块化编程规范,又是如何使用?本篇博文将一一解答以上疑问。

B、AMD-异步模块定义

AMD是”Asynchronous Module Definition”的缩写,即”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。

这里异步指的是不堵塞浏览器其他任务(dom构建,css渲染等),而加载内部是同步的(加载完模块后立即执行回调)。

AMDRequireJS在推广过程中对模块定义的规范化产出,它是一个概念,RequireJS是对这个概念的实现,就好比JavaScript语言是对ECMAScript规范的实现。AMD是一个组织,RequireJS是在这个组织下自定义的一套脚本语言。

不同于CommonJS,它要求两个参数:

require([module], callback);

第一个参数[module],是一个数组,里面的成员是要加载的模块,callback是加载完成后的回调函数。如果将上述的代码改成AMD方式:

require([math], function(math) { math.add(2, 3);})

其中,回调函数中参数对应数组中的成员(模块)。

requireJS加载模块,采用的是AMD规范。也就是说,模块必须按照AMD规定的方式来写。

具体来说,就是模块书写必须使用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接写在define()函数之中。

define(id, dependencies, factory);

假定现在有一个math.js文件,定义了一个math模块。那么,math.js书写方式如下:

// math.jsdefine(function() { var add = function(x, y) { return x + y; } return { add: add }})

加载方法如下:

// main.jsrequire([math], function(math) { alert(math.add(1, 1));})

如果math模块还依赖其他模块,写法如下:

// math.jsdefine([dependenceModule], function(dependenceModule) { // ...})

require()函数加载math模块的时候,就会先加载dependenceModule模块。当有多个依赖时,就将所有的依赖都写在define()函数第一个参数数组中,所以说AMD是依赖前置的。这不同于CMD规范,它是依赖就近的。

CMD

C、CMD-同步模块定义

CMDCommon Module Definition通用模块定义,是SeaJS在推广过程中对模块定义的规范化产出,是一个同步模块定义,是SeaJS的一个标准,SeaJSCMD概念的一个实现,SeaJS是淘宝团队玉伯提供的一个模块开发的js框架。CMD规范是国内发展出来的,就像AMD有个requireJSCMD有个浏览器的实现SeaJSSeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同。

CMD通过define()定义,没有依赖前置,通过require加载jQuery插件,CMD是依赖就近,在什么地方使用到插件就在什么地方require该插件,即用即返,这是一个同步的概念。

CMD规范中,一个模块就是一个文件。代码的书写格式如下:

define(function(require, exports, module) { // 模块代码});

其中,

AMD是依赖关系前置,在定义模块的时候就要声明其依赖的模块;

CMD是按需加载依赖就近,只有在用到某个模块的时候再去require,示例代码如下:

// CMDdefine(function(require, exports, module) { var a = require(./a) a.doSomething() // 此处略去 100 行 var b = require(./b) // 依赖可以就近书写 b.doSomething() // ... })// AMD 默认推荐的是define([./a, ./b], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() ...})

D、CommonJS 规范

CommonJS规范是通过module.exports定义的,在前端浏览器里面并不支持module.exports,通过node.js后端使用。Nodejs端使用CommonJS规范,前端浏览器一般使用AMDCMDES6等定义模块化开发规范。

CommonJS的终极目标是提供一个类似PythonRubyJava的标准库。这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用就可以运行在不同的JavaScript解释器和不同的主机环境中。

在兼容CommonJS的系统中,你可以使用JavaScript开发以下程序:

,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。这标志”Javascript模块化编程”正式诞生。NodeJSCommonJS规范的实现,webpack也是以CommonJS的形式来书写。

node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。

var math = require(math);

然后,就可以调用模块提供的方法:

var math = require(math);math.add(2,3); // 5

CommonJS定义的模块分为:模块引用(require)、 模块定义(exports)、模块标识(module)。

其中,

虽说NodeJS遵循CommonJS的规范,但是相比也是做了一些取舍,添了一些新东西的。

NPM作为Node包管理器,同样遵循CommonJS规范。

下面讲讲commonJS的原理以及简易实现:

1、原理

浏览器不兼容CommonJS的根本原因,在于缺少四个Node.js环境变量。

moduleexportsrequireglobal

只要能够提供这四个变量,浏览器就能加载CommonJS模块。

下面是一个简单的示例。

var module = { exports: {}};(function(module, exports) { exports.multiply = function (n) { return n * 1000 }; }(module, module.exports))var f = module.exports.multiply; f(5) // 5000

上面代码向一个立即执行函数提供 module 和 exports 两个外部变量,模块就放在这个立即执行函数里面。模块的输出值放在 module.exports 之中,这样就实现了模块的加载。

2、Browserify 的实现

Browserify是目前最常用的CommonJS格式转换工具。

请看一个例子,main.js模块加载foo.js模块。

// foo.jsmodule.exports = function(x) { console.log(x);};// main.jsvar foo = require("./foo");foo("Hi");

使用下面的命令,就能将main.js转为浏览器可用的格式。

$ browserify main.js > compiled.js

其中,Browserify到底做了什么?安装一下browser-unpack,就清楚了。

$ npm install browser-unpack -g

然后,将前面生成的compile.js解包。

$ browser-unpack < compiled.js

[ { "id":1, "source":"module.exports = function(x) {\n console.log(x);\n};", "deps":{} }, { "id":2, "source":"var foo = require(\"./foo\");\nfoo(\"Hi\");", "deps":{"./foo":1}, "entry":true }]

可以看到,browerify将所有模块放入一个数组,id属性是模块的编号,source属性是模块的源码,deps属性是模块的依赖。

因为main.js里面加载了foo.js,所以deps属性就指定./foo对应1号模块。执行的时候,浏览器遇到require(./foo)语句,就自动执行1号模块的source属性,并将执行后的module.exports属性值输出。

E、ES6

有关es6模块特性,强烈推荐阮一峰老师的:ECMAScript 6 入门 – Module 的语法专栏。

要说ES6模块特性,那么就先说说ES6模块跟CommonJS模块的不同之处。

CommonJS模块输出的是值的拷贝(原始值的拷贝),也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

// a.jsvar b = require(./b);console.log(b.foo);setTimeout(() => { console.log(b.foo); console.log(require(./b).foo);}, 1000);// b.jslet foo = 1;setTimeout(() => { foo = 2;}, 500);module.exports = { foo: foo,};// 执行:node a.js// 执行结果:// 1// 1// 1

上面代码说明,b 模块加载以后,它的内部 foo 变化就影响不到输出的 exports.foo 了。这是因为 foo 是一个原始类型的值,会被缓存。所以如果你想要在CommonJS中动态获取模块中的值,那么就需要借助于函数延时执行的特性。

// a.jsvar b = require(./b);console.log(b.foo);setTimeout(() => { console.log(b.foo); console.log(require(./b).foo);}, 1000);// b.jsmodule.exports.foo = 1; // 同 exports.foo = 1 setTimeout(() => { module.exports.foo = 2;}, 500);// 执行:node a.js// 执行结果:// 1// 2// 2

所以我们可以总结一下:

javascript视频教学

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。