这部分主要总结深入浅出Node.js的第二章

 一)CommonJs

    1.1CommonJs模块定义

  二)Node的模块实现

    2.1模块分类

    2.2 路径分析和文件定位

      2.2.1 路径分析

      2.2.2 文件定位

    2.3 模块编译

      2.3.1 javascript模块编译

      2.3.2 exports和module.exports

  三)前后端共用的模块

    3.1 前后端侧重点

    3.2 AMD和CMD

    3.3 兼容多种模块规范  

一) CommonJs  在CommonJs的官网上写着这样一句话 javascript:not just for browsers any more  CommonJs是一种规范,它涵盖了模块.二进制.Buffer.文件系统.包管理等,node就是借鉴了CommonJs的Modules规范实现了一套非常易用的模块系统

  1.1 CommonJs模块的定义  主要分模块引用.模块定义.模块标识  CommonJs的模块导入导出机制可以使用户不必考虑变量污染等问题

/*模块引入*/
var math = require("math"); /*模块标识 传递给require的参数*/
/*模块定义*/
exports.add = function(a,b) {
return a + b;
}

二)Node的模块实现   在Node中对规范进行了一定的取舍,也增加了一定自身需要的特性 node中引入模块主要分为3个步骤

  1. 路径分析
  2. 文件定位
  3. 编译执行

  2.1 Node中的模块分类  在node中模块分为两类 Node提供的模块,核心模块. 用户编写的模块,文件模块

  • 核心模块 在node的源代码编译的过程中被编译进了二进制执行文件,在node进程启动的时候,部分的核心模块被直接加载到内存,所以引用这部分模块不需要文件的定位和编译执行,并且在路径分析中优先判断,所以加载速度最快
  • 文件模块  运行时动态的加载,需要完成的路径解析,文件定位,编译执行过程,加载速度相对较慢    

无论是核心还是文件模块 Node都会采用缓存优先的策略,不同于浏览器中缓存的是文件,Node中缓存的是编译和执行之后的对象

  2.2 路径分析和文件定位

    2.2.1 路径分析 node中根据require()中传入的标识符,来进行模块的查找和定位,对不同类型的标识符查找定位的方式会有一些区别  标识符只要分为下面几类

  1. 核心模块(核心模块的优先级的优先级仅次于缓存加载,在Node的源代码的编译过程中已经被编译成了二进制的代码,加载过程最快 无法加载与核心模块相同标识符的自定义模块,只能通过其他的方式加载与核心模块相同标识符的自定义模块)
  2. 绝对路径或者相对路径的文件模块(通过将相对路径和绝对路径转换成真实路径,并且以真实路径作为索引,将编译后的结果放到缓存中,由于指明了确切的文件位置,所以其加载速度慢于核心模块)
  3. 非路径形式的文件模块,通常为自定义模块(当前文件目录下的node_modules  父目录下的node_modules 父目录的父目录下的node_modules  沿路径向上逐级递归,直到根目录的node_modules   很像原型链的查找 所以自定义模块的查找速度最慢)       

    2.2.2 文件定位

  • 文件的扩展名分析 CommonJs中允许在标识符中不包含扩展名,这种情况下Node会按照.js,.node,.json的次序补足扩展名 在require的时候,是同步阻塞的判断文件是否存在的,此时加入你确定需求的文件的扩展名字是.node,.json,在require的时候补足扩展名,能加快一下访问速度
  • 目录分析和包  如果你通过require()的标示符查找到一个目录,Node会将这个目录当做包处理 Node会在当前的目录下查找package.json文件,通过JSON.parse()解析出包描述对象,从中读取出main属性执行的文件进行定位,如果该文件不存在扩展名,则进入扩展名解析的步骤 如果main执行的文件错误或者不存在package.json文件,Node会将index当做默认的扩展名,然后依次的查找index.js,index.json,index.json
  • 如果在通过上面的方式仍然没有定位到相应的文件或者模块,则上升到下一个模块路径进行查找    

  2.3 模块编译  在node中文件模块都是对象.类似下面的定义 在定位到具体的文件后,node会创建一个模块对象,然后载入和编译

  

function Module(id,parent) {
this.id = id;
this.exports = {};
this.parent = parent;
if(parent && parent.children) {
parent.children.push(this);
}
this.filename = null;
this.loaded = false;
this.children = [];
}

  在引入模块的时候,对不同扩展名的文件node的载入方式也不同

  • .js 通过fs模块同步读取文件后编译执行
  • .node C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件  (.node模块是通过C/C++编译后生成的,所以只有加载和执行的过程,C/C++模块的优势是执行效率更高但相对于javascript模块来说开发门槛更高)
  • .json 通过fs模块同步读取文件后,用JSON.parse()解析返回结果
  • 其余扩展名 都会当做.js文件载入

  2.3.1 javascript模块编译 

    在编译的过程中,node会对获取到的内容进行封装 类似于下面的样子

(function(exports,require,module,__filename,__dirname){
/**
* 你的js代码
*/
})

这样模块之间就进行了作用域的隔离 然后通过vm原生模块的runInThisContext()方法执行返回一个function对象 然后将之前的模块对象的exports,require()方法,module,文件路径等信息传入给函数执行,执行之后将exports属性返回给调用方,并且将编译后的结果根据路径索引缓存到Module._cache上

  exports和module.exports

    简单理解就是exports是module.exports的引用 具体看 exports和module.exports的区别

三)前后端共用的模块

  3.1 前后端侧重点

  • 浏览器端的javascript需要从同一个服务器分发到客户端,受限于带宽,读取速度慢
  • 服务器端的javascript是相同的代码需要多次的执行,受限于CPU和内存,后端代码直接从硬盘中读取加载速度快
  • node中模块的引入是同步的,但浏览器中同步的方式不可行    

  3.2 AMD和CMD规范

  • AMD模块定义的方式如下,它是CommonJs规范的一个延伸
define(id?,dependencies?,factory)

这里的factory就是实际代码的内容  在AMD中需要显示的定义一个模块,在node中这个过程是隐式包装

  • CMD CMD在引入的时候支持动态引入  

  3.3 兼容多种模块规范

;(function(name,definition){
var hasDefine = typeof define === 'define',
hasExports = typeof module !== 'undefined' && module.exports;
if(hasDefine) {
//AMD CMD
define(definition);
} else if(hasExports){
//node环境
module.exports = definition()
} else {
//挂在在window
this[name] = definition();
}
})(name,function(){
var obj = {};
retuen obj;
});

深入浅出node(2) 模块机制的更多相关文章

  1. Nodejs:Node.js模块机制小结

    今天读了<深入浅出Nodejs>的第二章:模块机制.现在做一个简单的小结. 序:模块机制大致从这几个部分来讲:JS模块机制的由来.CommonJS AMD CMD.Node模块机制和包和n ...

  2. 深入浅出Node.js---Connect模块解析 。转载

    文章地址:https://blog.csdn.net/zhangyuan19880606/article/details/51509205 1 Connect模块背景 Node.js的愿望是成为一个能 ...

  3. Node总结 模块机制

    1. Node中的模块分为两类.一个是node提供的模块,称为核心模块,如http, fs, path:另一类是用户编写的模块,称为文件模块. 2. require()方法接收一个标识符进行模块查找. ...

  4. 一个月时间整理《深入浅出Node.js》

    今天终于把朴灵老师写的<深入浅出Node.js>给学习完了, 这本书不是一本简单的Node入门书籍,它没有停留在Node介绍或者框架.库的使用层面上,而是从不同的视角来揭示Node自己内在 ...

  5. 浅谈NodeJs的模块机制

    J历史 我们都知道,js在刚被创建的时候,只是为了在网页上写一些小脚本而已,比如网页特效,表单验证等等,创立者也许没觉悟到以后的js会发展到如此规模.这是web1.0时代. 在web 2.0时代,各种 ...

  6. 《深入浅出Node.js》第2章 模块机制

    @by Ruth92(转载请注明出处) 第2章 模块机制 JavaScript 先天缺乏的功能:模块. 一.CommonJS 规范: JavaScript 规范的缺陷:1)没有模块系统:2)标准库较少 ...

  7. 深入浅出Node.js (2) - 模块机制

    2.1 CommonJS规范 2.1.1 CommonJS的出发点 2.1.2 CommonJS的模块规范 2.2 Node的模块实现 2.2.1 优先从缓存加载 2.2.2 路径分析和文件定位 2. ...

  8. Node.js入门:模块机制

    CommonJS规范      早在Netscape诞生不久后,JavaScript就一直在探索本地编程的路,Rhino是其代表产物.无奈那时服务端JavaScript走的路均是参考众多服务器端语言来 ...

  9. 【读书笔记】《深入浅出nodejs》第二章 模块机制

    1.什么是模块? 指在程序设计中,为完成某一功能所需的一段程序或子程序:或指能由编译程序.装配程序等处理的独立程序单位:或指大型软件系统的一部分. ----<百度百科> 2.JavaScr ...

随机推荐

  1. springMvc的日期转换之二

    方式一:使用@InitBinder注解实现日期转换 前台页面: 后台打印: 方式二:处理多种日期格式类型之间的转换 采用方式:由于binder.registerCustomEditor(Date.cl ...

  2. 聊聊从web session的共享到可扩展缓存设计

    先从web session的共享说起   许多系统需要提供7*24小时服务,这类系统肯定需要考虑灾备问题,单台服务器如果宕机可能无法立马恢复使用,这必定影响到服务.这个问题对于系统规模来说,从小到大可 ...

  3. 在Linux和Windows平台上操作MemoryMappedFile(简称MMF)

    操作系统很早就开始使用内存映射文件(Memory Mapped File)来作为进程间的共享存储区,这是一种非常高效的进程通讯手段..NET 4.0新增加了一个System.IO. MemoryMap ...

  4. xamarin绑定原生库的一些坑

    最近一个项目涉及到较多的第三方库的绑定技术,中间遇到了几个坑,记录下来与大家分享 绑定Jar库 monoandroid对原生库的调用都通过Android.Runtime.JNIEnv进行调入(http ...

  5. asp.net pipeline完整图

  6. 使用tornado,我们可以做什么?

    以下介绍都是建立在python2.x的基础上面,tornado使用任意版本皆可. 如果我们需要对外提供一个http server(web api)/websocket server时,我们都可以使用t ...

  7. ASP.NET MVC Model验证(四)

    ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...

  8. Android中自定义样式与View的构造函数中的第三个参数defStyle的意义

    零.序 一.自定义Style 二.在XML中为属性声明属性值 1. 在layout中定义属性 2. 设置Style 3. 通过Theme指定 三.在运行时获取属性值 1. View的第三个构造函数的第 ...

  9. Linux网络编程系列-常见疑惑

    1.并发TCP最大连接数 一个TCP连接有一个四元组唯一标识{local_ip, local_port, remote_ip, remote_port} client端建立连接请求时,通常让系统分配一 ...

  10. Win下必备利器之Cmder

    诚言,对于开发码字者,Mac和Linux果断要比Windows更贴心;但只要折腾下,Windows下也是有不少利器的.之前就有在Windows下效率必备软件一文中对此做了下记载:其虽没oh-my-zs ...