1. CommonJS规范产生背景

在后端,JavaScript的规范远远落后并且有很多缺陷,这使得难以使用JavaScript开发大型应用。比如:

  • 没有模块系统
  • 标准库较少
  • 没有标准接口
  • 缺乏包管理系统

CommonJS规范 的提出,主要是为了弥补JavaScript没有标准的缺陷。CommonJS API将通过定义处理许多常见应用程序需求的API来填补这一空白,最终提供与Python,Ruby和Java一样丰富的标准库。以达到像Python、Ruby和Java那样具备开发大型应用的基础能力,而不是停留在开发浏览器端小脚本程序的阶段。

应用程序开发人员能够使用CommonJS API编写应用程序,然后跨不同的JavaScript解释器和主机环境运行该应用程序。

2. CommonJS模块规范

CommonJS模块规范主要分为三部分:模块引用、模块定义、模块标识。

2.1 模块引用

//引入http模块,并赋值给变量http
var http = require('http');

require函数的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。当我们用require()获取module时,Node会根据module.id找到对应的module,并返回module. exports,这样就实现了模块的输出。

require函数使用一个参数,参数值可以带有完整路径的模块的文件名,也可以为模块名。

require("./module/b"); //相对路径
require("../node/module/c"); //绝对路径

文件目录结构如下:

2.2 模块定义

2.2.1 模块(module)是什么

CommonJS规范规定,一个文件就是一个模块,用module变量代表当前模块。 Node在其内部提供一个Module的构建函数。所有模块都是Module的实例。实例代码如下:

function Module(id, parent) {
this.id = id;
this.exports = {};
this.parent = parent;
this.filename = null;
this.loaded = false;
this.children = [];
} module.exports = Module;
var module = new Module(filename, parent);

每个模块内部,都有一个module对象,代表当前模块。它的属性如下:

  • module.id 模块的识别符,通常是带有绝对路径的模块文件名。
  • module.filename 模块的文件名,带有绝对路径。
  • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
  • module.parent 返回一个对象,表示调用该模块的模块。
  • module.children 返回一个数组,表示该模块要用到的其他模块。
  • module.exports 初始值为一个空对象{},表示模块对外输出的接口。

2.2.2 exports 属性

exports 属性是module对象的一个属性,它向外提供接口。
如 2.1模块引用 中示例,a.js引入b.js作为一个模块,当在b.js中定义如下方法时:

//加法
function add(num1,num2){
console.log(num1+num2);
}

在a.js中调用却报错

var addMethod = require("./module/b");
//调用模块中的add方法
addMethod.add(1,6);

b.js中的函数要能被其他模块使用,就需要暴露一个对外的接口,exports 属性用于完成这一工作。b.js中的方法定义修改如下:

exports.add = function(num1,num2){
console.log(num1+num2);
}

在a.js中能够调用。

2.3 模块标识

模块标识就是传递给require方法的参数,必须符合小驼峰命名的字符串,或者以.、..开头的相对路径,或者绝对路径,默认文件名后缀.js。在Node实现中,正是基于这样一个标识符进行模块查找的,如果没有发现指定模块会报错。

根据参数的不同格式,require命令去不同路径寻找模块文件。加载规则如下:

(1)如果参数字符串以“/”开头,则表示加载的是一个位于绝对路径的模块文件。比如,require('/home/marco/foo.js')将加载/home/marco/foo.js。

(2)如果参数字符串以“./”开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如,require('./circle')将加载当前脚本同一目录的circle.js。

(3)如果参数字符串不以“./“或”/“开头,则表示加载的是一个默认提供的核心模块(位于Node的系统安装目录中),或者一个位于各级node_modules目录的已安装模块(全局安装或局部安装)。

举例来说,脚本/home/user/projects/foo.js执行了require('bar.js')命令,Node会依次搜索以下文件。

/usr/local/lib/node/bar.js

/home/user/projects/node_modules/bar.js

/home/user/node_modules/bar.js

/home/node_modules/bar.js

/node_modules/bar.js

这样设计的目的是,使得不同的模块可以将所依赖的模块本地化。

(4)如果参数字符串不以“./“或”/“开头,而且是一个路径,比如require('example-module/path/to/file'),则将先找到example-module的位置,然后再以它为参数,找到后续路径。

(5)如果指定的模块文件没有发现,Node会尝试为文件名添加.js、.json、.node后,再去搜索。.js件会以文本格式的JavaScript脚本文件解析,.json文件会以JSON格式的文本文件解析,.node文件会以编译后的二进制文件解析。

(6)如果想得到require命令加载的确切文件名,使用require.resolve()方法。

CommonJS是同步的,意味着你想调用模块里的方法,必须先用require加载模块。这对服务器端的Nodejs来说不是问题,因为模块的JS文件都在本地硬盘上,CPU的读取时间非常快,同步不是问题。但如果是浏览器环境,要从服务器加载模块。模块的加载将取决于网速,如果采用同步,网络情绪不稳定时,页面可能卡住,这就必须采用异步模式。所以,就有了 AMD解决方案。下一篇我们开始介绍模块化规范的AMD规范;

参考:

https://www.cnblogs.com/huiguo/p/7967241.html

https://nodejs.org/api/modules.html#modules_module_exports

Node.js相关——CommonJS规范的更多相关文章

  1. 19 — node 模块化 及 CommonJS规范 — CommonJS 的由来及各组织与 JS 的关系

    ECMAScript  对于不同的环境(运行平台),设计结构,理念,使用方式大相径庭. 1,浏览器 :DOM BOM 2,NodeJS :FS,HTTP 内置模块 :  第三方模块 : 内置模块 3, ...

  2. Node.js相关——package概念及NPM

    1. package 包 CommonJS的包规范允许我们将一组相关的模块组合到一起,形成一组完整的工具.CommonJS的包规范由 包结构 和 包描述文件 两个部分组成. 1.1 包结构 包实际上就 ...

  3. 【Node.js】3.Node.js和commomJS规范

    来源:http://javascript.ruanyifeng.com/ 目录 概述 module对象 module.exports属性 exports变量 AMD规范与CommonJS规范的兼容性 ...

  4. node.js之CommonJS

    1.CommonJS 我们只是在js文件中写下console.log('This is a test.');这句代码,node.js执行该js文件时: ( function(exports, requ ...

  5. Node.js 相关资料网站汇总

    地址:https://cnodejs.org/ nodejs中文网:http://nodejs.cn/ nodejs中文网:http://www.nodejs.net/ 相关API地址:http:// ...

  6. node采用的commonJs规范

    AMD与commonJS规范不同 同步加载 主要就是一个输出,一个引入,我也建了两个文件,一个输出文件一个引入文件 export.js ; ; ; function incCounter(){ cou ...

  7. 汇智课堂 Node.js相关课程

    Node.js入门 Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台, 用来方便地搭建快速的 易于扩展的网络应用· Node.js 借助事件驱动, 非阻塞I/O 模型 ...

  8. Node.js,commonjs,require

    环境: Node应用由模块组成,采用CommonJS模块规范. node的全局对象是global,没有window这个对象. process表示当前执行的进程,挂在global之下. CommonJS ...

  9. node.js相关

    node node最大的特点是单线程,因此一个只能有一个任务运行,大量采用异步操作. 某一个任务的后续操作一般采用回调函数的形式 var callback = function (error, val ...

随机推荐

  1. Android JNI中C和JAVA代码之间的互相调用

    关于Android studio中使用NDK/JNI环境和入门:http://blog.csdn.net/quan648997767/article/details/64923143 1. C代码回调 ...

  2. 【google面试题】求1到n的正数中1出现的次数的两种思路及其复杂度分析

    问题描写叙述: 输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.比如输入12,从1到12这些整数中包括1 的数字有1.10.11和12.1一共出现了5次. 这是一道广为流传的googl ...

  3. 【Spark】Spark-Redis连接池

    Spark-Redis连接池 jedispool returnresource 遭废弃 用 什么替代_百度知道 spark-stream 访问 Redis数据库示例 - 阿里云 [Redis]Java ...

  4. CSOM中如何取到managed metadata类型字段的类型信息

    Field.fieldTypeKind返回的是Invalid [解决方法] There is no "Metadata" type of field in the SP.Field ...

  5. OSError: Could not find library geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so

    OSError: Could not find library geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so ...

  6. JavaScript判断变量是否为数组的方法(Array)

    废话不多说直接上一个代码: 1.这里是通用的检测方法 /* * 判断是否是数组 */ function isArray(obj){ return Object.prototype.toString.c ...

  7. 比特币 Bitcoin 是什么,我勒个去,哈耶克果然超前——货币的非国有化,容我思量一下【转载+整理】

    原文地址 比特币矿业史(上):故事的开始,CPU 时代 比特币矿业史(中):群众的觉醒 ,GPU 时代 比特币矿业史(下):巨头的诞生 ,ASIC 时代 本文内容 引子 0 序 1 故事的开始 : C ...

  8. 【树莓派】在树莓派的Android系统中安装APK应用

    树莓派3 Android TV安装APK应用教程 本文摘自:http://www.mz6.net/news/android/6867.html 树莓派3 Android TV怎样安装软件?对于熟悉AD ...

  9. 微软BI 之SSAS 系列 - 实现Cube 以及角色扮演维度,度量值格式化和计算成员的创建

    在熟悉完下面这三种维度的创建方式之后,就可以开始创建我们的第一个 Cube 了. SSAS 系列 - 自定义的日期维度设计 SSAS 系列 - 基于雪花模型的维度设计 SSAS系列 - 关于父子维度的 ...

  10. Mina.Net实现的UDP多路广播

    主要用于未确定主机地址的情况下,可以使用多路广播和服务端通信,下面是官方提供的DEMO. using System; using System.Net; using System.Net.Socket ...