模块机制 之commonJs、node模块 、AMD、CMD
在其他高级语言中,都有模块中这个概念,比如java的类文件,PHP有include何require机制,JS一开始就没有模块这个概念,起初,js通过<script>标签引入代码的方式显得杂乱无章,语言自身也缺乏组织和约束能力,所以人们不得不以各种命名空间等方式认为的约束代码,达到安全易用的目的。经历十几年的发展,js也执行起了响应的规范,commonJS规范的提出算是一个重要的里程碑。
一、commonJS规范
commonJS规范的愿景是希望JavaScript能在任何地方上运行,出发点主要是想弥补起初没有模块系统、标准库较少、没有标准接口,缺乏包管理器等缺陷,希望JavaScript可以具备和java等语言具备的开发大型应用能力的能力。它为JavaScript开发大型应用程序指明了一条非常好的道路,node正是借鉴这个的规范慢慢的出现在人们的视野中,且逐渐变得强大。
commonJS对模块的定义十分简单,主要分为模块引用、模块定义、模块标识几个部分。
根据这个规范,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数都是私有的,对其他文件不可见。这个规加载的模块是同步的,加载完成才能执行后面的操作。
该规范主要是通过 module.exports向外提供接口,加载某个模块,其实是加载该模块的module.exports属性。
//test1.js 模块文件
var a=10;
var dosomething = function(){
/**代码**/
}
//模块定义
module.exports.a = a;
module.exports.dosomething = dosomething; var test2 = require('./test1.js'); //模块引用 其中./test1.js就是模块标识
console.log(test1.a);
console.log(test1.dpsomething());//调用test1完成之后,就可以去使用test1所暴露出来的接口(变量)
特点:
1、所有代码都运行在模块作用域,不会污染全局作用域。
2、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
3、模块加载的顺序,按照其在代码中出现的顺序。
4、便于服务器端和桌面应用使用。
缺点:
因为该规范加载模块是同步的,浏览器获取一个资源是通过发送http请求之后获得的,这意味着会出现阻塞加载,从而在浏览器进程出现假死现象。所以浏览器需要的是异步加载的规范,这这是下面所讲的AMD和CMD规范。
二、node模块
node在实现模块的实现中并非完全按照commonJS规范实现,而是对上面模块规范做了一定的取舍,同时也增加了自身需要的特性。node在实现exports、require、module主要经历几个过程
1、路径分析 2、文件定位 3、编译执行
node中的模块主要分为两类,一类是nodet提供的核心模块,如fs 、http等模块; 一类是用户编写的文件模块。
核心模块在node代码编译的过程中,编译成了二进制执行文件,在node进程启动时候,部分核心模块被加载进内存中,所以核心模块在引入时候,文件定位和编译执行可以省略掉,并在路径分析中被优先判断,所以加载的速度是十分快的。
几个特点
1、优先从缓存中加载
node对引入的模块都会进行缓存,减少二次开销。和浏览器缓存静态脚本不一样的是,浏览器缓存的是文件,node缓存的是编译和执行之后的文的对象。所以require()方法对相同的模块一律采用缓存优先的策略。
2、核心模块是有c/c++和JavaScript编写部分,c/c++在node目录下的src下,JavaScript在lib目录下。编译的过程是讲JavaScript模块文件编译成c/c++代码,在引入核心模块的过程中,对模块代码进行了从头到尾的包装,让require、module、exports这些变量能够使用,最后执行和到处exports对象。
3、b包管理机制
node组织了自身的核心模块,也使得第三方的文件模块都可以有序的编写和使用,但是在第三方模块中,模块之间散列在各地,不能相互应用,在模块之外,包和NPM是讲各种模块联系起来的一种机制。
三、模块的侧重点
在JavaScript和node出现之后,一些模块可以在前后端实现公用,前后端的js分别搁置在HTTP的两端,扮演的角色也不一样,浏览器的js需要从服务器分发到多个客户端执行,而服务端则是相同的代码多次执行,前者瓶颈在于宽带,后者在于CPU和内存等资源,前者通过网路读取,后者通过磁盘读取速度显而易见,所以node模块引入几乎是同步的,但是,如果前端的额代码也是采用同步当时引用,这样可能因为UI需要等待脚本的加载,这样就会影响用户的体验,这样commonJS的同步加载就不能满足前端的应用市场了,必须需要其他的加载模式,这样AMD和CMD就营运而生了。
四、AMD
AMD(asynchronous module define)异步加载定义,该规范是RequireJS 在推广过程中对模块定义的规范化产出的,是commonJS的一个延伸。
AMD模块需要define来确定一个模块,用require()加载模块。而node中是隐士包装的,他们的目的都是达到作用域的隔离,仅在需要的时候被引入。
异步的模块加载不影响后面语句的执行,所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
//定义模块
define("c", ["a", "b"], function(a, b) { //c:模块id a和b是模块的依赖 都是可选的
a.dosomething(); //加载依赖模块a完成之后执行回调
}); //用require加载模块
require(['c'], function ( c) {
// 这里写其余的代码
c.doSomething();
});
五、CMD
通用模块定义,该规范是SeaJS 在推广过程中对模块定义的规范化产出的,有兴趣可以看《前端代码模块加载器之sea,js》。 和AMD很类似,
require, exports, module通过形参的形式传递给模块,在需要模块的时候,随时调用require()去调用。
c是模块的名称,['a']是依赖项,这两个可省略,一般是省略的。
define('c',['a'],function(require, exports, module) {
// 模块代码
}); 如果b模块中想引用a模块,只需require()就可以了
define(function(require,exports,module){
var a = require('a')
});
六、AMD和CMD的区别
1、对于依赖模块,AMD是依赖前置,CMD依赖就近
// AMD
define(['./a', './b'], function(a, b) {
// 依赖必须一开始就写好
a.doSomething()
/******代码*******/
b.doSomething() ...
}) // CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
/******代码*******/
var b = require('./b') // 依赖可以就近书写
b.doSomething() // ...
})
2、执行顺序
AMD是提前执行,CMD是延迟执行
3、提供的API
AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。
AMD 里,require 分全局 require 和局部 require,都叫 require。
CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
为了更好理解不同模块化开发理念,建议参考:RequireJs和seaJs的差别。
七、兼容多种模块规范
为了让一个模块可有运行在前后端,保持前后端的一致性,如下就是展示将test()方法定义到不同的环境中,它能够兼容node 、AMD、CMD及常规的浏览器中:
;(function(name, definition){
//检测上下文环境是不是AMD或CMD
var hasDefined = typeof defined == 'function',
//检测上下文环境是不是node
hasExports =typeof module !=='undefined' && module.exports; if(hasDefined){
defined(definition); //AMD或CMD
}else if( hasExports){
module.exports = definition(); //node
}else{
this[name] = definition(); //将执行的结果挂在window变量中,浏览器中的this这指向window
}
})('test',function(){
var test = function(){}
return test;
})
简洁点:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global)));
}(this, (function (exports) {
'use strict';
//code
})));
模块机制 之commonJs、node模块 、AMD、CMD的更多相关文章
- JavaScript模块化CommonJS/AMD/CMD/UMD/ES6Module的区别
目录 JS-模块化进程 原始的开发方式 CommonJS && node.js AMD && Require.js CMD && Sea.js UMD ...
- 浅谈NodeJs的模块机制
J历史 我们都知道,js在刚被创建的时候,只是为了在网页上写一些小脚本而已,比如网页特效,表单验证等等,创立者也许没觉悟到以后的js会发展到如此规模.这是web1.0时代. 在web 2.0时代,各种 ...
- Typescript学习笔记(五) 模块机制
javascript从es5之前都缺少一种模块机制,无法通过js引入文件,于是requirejs等等的加载器应运而生.这些加载器的使用也并不统一,产生了amd,commonjs,umd等等的规范,各有 ...
- 【前端知识体系-NodeJS相关】对NodeJS模块机制的理解
1. CommonJS模块规范 1.1 模块引用 var math = require('math'); 1.2 模块定义 [!NOTE] 上下文提供exports对象用于导出当前模块的方法和变量,并 ...
- 深入了解Node模块原理
深入了解Node模块原理 当我们编写JavaScript代码时,我们可以申明全局变量: var s = 'global'; 在浏览器中,大量使用全局变量可不好.如果你在a.js中使用了全局变量s,那么 ...
- Nestjs模块机制的概念和实现原理
1 前言 Nest 提供了模块机制,通过在模块装饰器中定义提供者.导入.导出和提供者构造函数便完成了依赖注入,通过模块树组织整个应用程序的开发.按照框架本身的约定直接撸一个应用程序,是完全没有问题的. ...
- vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结
vue—你必须知道的 目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...
- 理解JS中的模块规范(CommonJS,AMD,CMD)
随着互联网的飞速发展,前端开发越来越复杂.本文将从实际项目中遇到的问题出发,讲述模块化能解决哪些问题,以及如何使用 Sea.js 进行前端的模块化开发. 恼人的命名冲突 我们从一个简单的习惯出发.我做 ...
- JS模块之AMD, CMD, CommonJS、UMD和ES6模块
CommonJS 传送门 同步加载,适合服务器开发,node实现了commonJS.module.exports和require 判断commonJS环境的方式是(参考jquery源码): if ( ...
随机推荐
- greenplum集群某台机器磁盘占用100%处理方式
一.问题描述 使用gpfdist往集群中导入大量数据, 一段时间后连接退出,集群无法连接 二.问题定位 使用如下命令查看: gpstate -s mdw-:gpadmin-[INFO]:- Segme ...
- Django ORM那些相关操作
一般操作 https://docs.djangoproject.com/en/1.11/ref/models/querysets/ 官网文档 常用的操作 <1> all() ...
- Python入门之函数的装饰器
本章目录: 装饰器: 一.为什么要用装饰器 二.什么是装饰器 三.无参装饰器 四.装饰器语法糖 五.认证装饰器实现 六.叠加多个装饰器 七.带参装饰器 ======================== ...
- 上传视频使用ffmpeg自动截取缩略图
上传视频之后,有的需要显示缩略图,而不是仅仅显示视频名称的列表,这时候就需要对上传的视频截取缩略图. 简单粗暴点,将以下代码作为工具类复制粘贴即可: package com.util; import ...
- SpringMVC(十一):SpringMVC 处理输出模型数据之SessionAttributes
Spring MVC提供了以下几种途径输出模型数据:1)ModelAndView:处理方法返回值类型为ModelAndView时,方法体即可通过该对象添加模型数据:2)Map及Model:处理方法入参 ...
- hdu2062 Subset sequence----递推
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2062 题目大意: 给出n和m,集合{1,2,,,,n}的非空子集,按照一定方式排列,例如n==3时, ...
- Resource 的 IsSealed 问题
WFP 的 Generic.xaml ,App.xaml 等中的资源会被调用 Freezable. 在后台对该资源进行修改等操作会被提示.资源为密封对象. 如果,确定需要在后台对资源进行修改. 则需要 ...
- angularjs1.x版本,父子组件之间的双向绑定
今天遇到了一个angularjs的坑, ng-repeat和ng-if会改变他所包含的html中绑定变量的作用域. angularjs自定义指令,可以定义四种变量,通过 =,@,&双向绑定,单 ...
- [ZooKeeper] 2 环境搭建
上一篇中我们介绍了 ZooKeeper 的一些基本概念,这篇我们讲一下 ZooKeeper 的环境搭建. ZooKeeper 安装模式 单机模式:ZooKeeper 运行在一台服务器上,适合测试环境: ...
- Linux的基本命令(CentOS)
1.ll:列出当前文件夹下所有的文件夹的详细信息.2.ls:列出当前文件夹下的所有文件(只有名字) ls -a查看隐藏文件 ls / 根目录下的文件 pwd 查看当前所在目录 who ...