浅谈NodeJs的模块机制
J历史
我们都知道,js在刚被创建的时候,只是为了在网页上写一些小脚本而已,比如网页特效,表单验证等等,创立者也许没觉悟到以后的js会发展到如此规模。这是web1.0时代。
在web 2.0时代,各种前端库,前端框架被开发出来,jquery,angular就是代表。此时js的功能也就从写写小特效啥的跃迁到了应用开发的级别上。可以说,js经历了工具类库,组件库,前端框架,前端应用的变迁。
于是在越来越广泛的应用中,js暴露了它先天就缺乏的一项功能:模块。在其它高级语言,都有模块的定义,java有类,python有import机制,ruby有require,php有require和include。而js此时还单纯的用script标签引入,用命名空间来约束代码,杂乱无章,于是,commonjs规范便应运而出。
commonJS的模块规范
commonjs规范的出发点就是让js在任何地方都能运行。它弥补了js此时的几点缺陷:
没有模块概念
标准库较少
没有标准接口
没有包管理系统
当然,如今commonjs规范已经解决了大部分问题,而且涵盖了模块,二进制,Buffer,字符集编码,I/O流,单元测试,web服务网关接口,包管理,等。
commonjs对模块的定义很简单,包含了模块定义,模块引用,模块标识3个部分。
模块引用
var xx = require('xxx')
关键字require来接受模块标识,引入这个模块的API到上下文中。
模块定义
一个例子来解释:
//add.jsfunction add(a,b){ return a+b;
}// 这样导出的 add是作为 exports 的一个方法被导出的exports.add = add;// main.jsvar Add = require('add');console.log(Add.add(1,2));//Add是require引入的模块名,add是方法名。
node在编译的时候,会把代码封装成如下的样子
// require 是对 Node.js 实现查找模块的 Module._load 实例的引用// __finename 和 __dirname 是 Node.js 在查找该模块后找到的模块名称和模块绝对路径(function(exports,require,module,__filename,__dirname){ function add (a,b){ return a+b;
}
exports.add = add;
})
为了将函数直接导出成一个模块,而不是一个方法,用到了全局变量module,下面就是我们常见的样子了:
// add.jsfunction add (a,b){ return a+b ;
}module.exports = add;// main.jsvar add = require('add');console.log(add(1,2));
模块标识
模块标识就是require()里的参数,必须是小驼峰命名的字符串,或者是路径(./ 或../)。可以没有后缀.js
Node的模块机制
Node并不是完全按照commonjs规范来实现,而是进行了一些取舍,并增加了自己的一些特性。
Node中引入模块,经历3个步骤:
路径分析
文件定位
编译执行
Node中模块分为2种,核心模块(Node提供的)和文件模块(用户自己编写的)
Node对引入过的模块会进行缓存,就像前端浏览器会缓存静态脚本来提高性能一样。require()方法在对同一模块的二次加载一律采用缓存优先的方式。但是对核心模块的缓存检查优先于对文件模块的缓存检查。
路径分析
就是对模块标识的分析呗。
模块标识符在Node中分以下几类:
核心模块,如http,path
./ ../相对路径
/ 绝对路径
非路径形式的文件模块。
文件分析
如果模块标识符没有后缀,默认补上后缀从.js,.json,.node来次序查找。
模块编译
js编译上面已经提到了。Node对JS文件进行了包装,在头部添加了(function (exports, require, module, __filename, __dirname) {...})。这样每个模块都进行了作用域隔离。包装之后通过vm原生模块的runInThisContext()方法执行(类似eval,只是具有明确上下文,不污染全局)返回一个function。然后将上述参数传给这个function执行。
json编译更简单,Node直接用JSON.parse()方法编译json内容,得到的对象赋给exports。
包和NPM
commonjs的包规范包含2个组成部分,包结构和包描述文件
包描述文件:package.json
包结构:
package.json 包描述文件
bin: 存放可执行二进制文件的目录
lib 存放js代码的目录
doc. 存放文档的目录
test: 存放单元测试用例的代码
NPM的用法就不多说了。
前后端公用模块
自从Node出来以后,js也可以运用在后端。但是前后端的JS扮演的角色不同,浏览器端的js需要经历从同一个服务器分发到多个客户端执行。服务端的js则是相同的代码多次执行。前者的瓶颈在于带宽。后者的瓶颈在于CUP和内存。前者需要通过网络加载。后者从磁盘中加载。
因为Node基于commonjs规范来同步的加载模块的。前端若用同步方式来加载模块,在用户体验上会造成很大的问题。UI在初始化的时候需要等待很长时间来加载js脚本。所以提出了异步模块定义AMD和CMD。这在我的另一篇博客中有提到。就不多说了。
为了写个能兼容前后端的模块规范,类库的开发者要把代码包装在一个 闭包里。这样就能兼容Node,AMD,CMD和常见的浏览器。
浅谈NodeJs的模块机制的更多相关文章
- 浅谈Python时间模块
浅谈Python时间模块 今天简单总结了一下Python处理时间和日期方面的模块,主要就是datetime.time.calendar三个模块的使用.希望这篇文章对于学习Python的朋友们有所帮助 ...
- 浅谈Java的反射机制和作用
浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...
- 浅谈:Redis持久化机制(一)RDB篇
浅谈:Redis持久化机制(一)RDB篇 众所周知,redis是一款性能极高,基于内存的键值对NoSql数据库,官方显示,它的读效率可达到11万次每秒,写效率能达到8万次每秒,因为它基于内存以及存 ...
- 浅谈:Redis持久化机制(二)AOF篇
浅谈:Redis持久化机制(二)AOF篇 上一篇我们提及到了redis的默认持久化方式RDB,是一种通过存储快照数据方式持久化的机制,它在宕机后会丢失掉最后一次更新RDB文件后的数据,这也是由于它 ...
- 浅谈C语言中断处理机制
一.中断机制 1.实现中断响应和中断返回 当CPU收到中断请求后,能根据具体情况决定是否响应中断,如果CPU没有更急.更重要的工作,则在执行完当前指令后响应这一中断请求.CPU中断响应过程如下:首先, ...
- 浅谈 ArrayList 及其扩容机制
浅谈ArrayList ArrayList类又称动态数组,同时实现了Collection和List接口,其内部数据结构由数组实现,因此可对容器内元素实现快速随机访问.但因为ArrayList中插入或删 ...
- 60.浅谈nodejs中的Crypto模块
转自:https://www.cnblogs.com/c-and-unity/articles/4552059.html node.js的crypto在0.8版本并没有改版多少,这个模块的主要功能是加 ...
- 浅谈nodejs中HTTP模块应用
这里给大家分享下后端人员如果利用nodejs对数据的一些处理情况 适用于初学者使用 大牛勿喷 给大家分享下主要后端思想部分代码,前端部分就不展示了 const http = require(&quo ...
- 浅谈Nodejs应用的主文件index.js的组成部分
前言 Node妹子的问世,着实让我们前端攻城狮兴奋了一把,尤其本屌听说Javascript可以写服务端后,兴奋的像是看到了二次元萝莉的胖子...(●'◡'●).呃哼...YY先到这里,原谅本屌是个二次 ...
随机推荐
- 【云安全与同态加密_调研分析(2)】国外云安全标准建议组织——By Me
国际上比较有影响力的云安全组织: ◆2. 国外云安全标准建议组织(云安全建议白皮书)◆ ◆云安全标准建议组织(主要的)◆ ◆标准建议组织介绍◆ ◆相关建议白皮书制定◆ ◆建立的相关模型参考◆ ◆备注( ...
- MySQL 最基本的SQL语法/语句
DDL—数据定义语言(Create,Alter,Drop,DECLARE) DML—数据操纵语言(Select,Delete,Update,Insert) DCL—数据控制语言(GRANT,REVOK ...
- Spark2.0机器学习系列之1: 聚类算法(LDA)
在Spark2.0版本中(不是基于RDD API的MLlib),共有四种聚类方法: (1)K-means (2)Latent Dirichlet allocation (LDA) ...
- Python第一个爬虫学习
在网上查看大神的关于Python爬虫的文章,代码如下: #coding=utf-8 import urllib import re def getHtml(url): page = urllib.ur ...
- Redis操作手册
一.Redis简介 1.1 NoSQL NoSQL,泛指非关系型数据库,NoSQL数据库分为四大类:键值存储数据库(Redis,Voldemort,Oracle BDB).列存储数据库(HBase,R ...
- xe7开发的安卓程序,体积宏大--112M!
原因没找到,但似乎可以这样解决: 解决过程:因为代码很少,所以我重新建立一个空白程序,把代码复制过去,一字不差.重新编译, 关键的时刻到了:不要连上真机,在编译完成时,系统提示是否要启动android ...
- DataTable转换成IList
//文章出处: http://www.cnblogs.com/hlxs/archive/2011/05/09/2087976.html DataTable转换成IList 在用C#作开发的时候经常要把 ...
- Spring-1-E Game(HDU 5011)解题报告及测试数据
Game Time Limit:1000MS Memory Limit:65536KB Description Here is a game for two players. The rule ...
- VS 和 Eclipse 的一些快捷键记录
VS: 自动排版: Ctrl+K+F 选项卡之间的切换: Ctrl+Tab 统一缩进: Shift+Tab Ctrl + M + O: 折叠所有方法 Ctrl + M + L: 展开所有方法 Ecli ...
- ImageNet历年冠军和相关CNN模型
ImageNet 是一个超过15 million的图像数据集,大约有22,000类. 是由李飞飞团队从2007年开始,耗费大量人力,通过各种方式(网络抓取,人工标注,亚马逊众包平台)收集制作而成,它作 ...