从零学习node.js之模块规范(一)


Posted in Javascript onFebruary 21, 2017

什么是Node.js?

很多初学者并没有真正地理解Node.js到底是什么。nodejs.org网站中的描述也没有多大帮助。

首先要清楚Node不是一个Web服务器,这十分重要。它本身并不能做任何事情。它无法像Apache那样工作。如果你希望它成为一个HTTP服务器,你必须借助它内置库自己编写。Node.js只是计算机上执行代码的另一种方式,它是一个简单的JavaScript Runtime.

模块化

在讲解CommonJS, AMD, CMD这些概念之前,我们首先俩了解下js的模块化。模块化,顾名思义,就是将项目按照功能或者其他逻辑进行分解处理,每个部分只处理一个功能,进行功能的解耦处理,方便以后的开发和维护。那么模块化必须具有以下的能力,才能进行模块的拆分和组装:

  1. 定义封装的模块;
  2. 定义新模块对其他模块的依赖;
  3. 可对其他模块的引入支持;

那么就需要一套规范准则来定义这些能力,于是就出现了CommonJS, AMD, CMD等。

1. CommonJS

CommonJS原先叫做ServerJS,是js在服务端的规范,node使用的就是这种规范。根据CommonJS规范,一个单独的文件就是一个模块,require用来加载一个模块,exports用来向外部暴露该模块里的方法或属性。

例如:

// hello.js
function say(username){
 console.log( 'hello, '+username );
}

exports.say = say;

=============

// main.js
var person = require('./hello');

person.say('wenzi'); // hello, wenzi
person.say('师少兵'); // hello, 师少兵
person.say('NUC'); // hello, NUC

同时,require语句可以写在文件中的任何位置,只要使用之前引用之前即可,不一定要写在文件的最前面。不过,为了代码更易阅读,能直观地看到当前引用了哪些模块,最好是放在文件的最前面。

EXPORTS与MODULE.EXPORTS的区别

可能有人见过直接使用exports的,有的是使用module.exports的,这里稍微的讲解下这两者的区别。

先举个简单的例子:

var a = {name:'wenzi'};
var b = a;

console.log(a); // {name: "wenzi"}
console.log(b); // {name: "wenzi"}

a和b输出的结果是一样的。现在我改变下b中name的值:

b.name = 'shaobing';

console.log(a); // {name: "shaobing"}
console.log(b); // {name: "shaobing"}

a和b的输出结果都发生了改变。我再对b进行重新声明:

var b = {name:'师少兵'};

console.log(a); // {name: "shaobing"}
console.log(b); // {name: "师少兵"}

这三个例子输出了三种结果:

  1. 声明a对象,并把a赋值给b,然后a和b输出了相同的结果;
  2. 改变了b中的name,那么a中的name也跟着改变;
  3. 重新声明了b对象,那么a中的name则没有跟着b一起改变

解释:a 是一个对象,b 是对 a 的引用,即 a 和 b 指向同一块内存,所以1中的输出是一样的。当对 b 作修改时,即 a 和 b 指向同一块内存地址的内容发生了改变,a 也会体现出来,所以第2个例子输出也一样。当 b 被覆盖时,b 指向了一块新的内存,a 还是指向原来的内存,所以最后输出会不一样。

那么此时就可以引出exportsmodule.exports了:

  1. module.exports 初始值为一个空对象 {}
  2. exports 是指向的 module.exports 的引用
  3. require() 返回的是 module.exports 而不是 exports

如果module.exports发生了新指向,则exports无效;若module.exports没有发生变化,则直接exports即可。

2. AMD与RequireJS

说到AMD,不得不说到RequireJS,AMD从CommonJS社区独立出来,单独成为了AMD社区,AMD的流行,很大程度上也是依托了RequireJS作者的推广。

AMD规范中,默认推荐的模块格式是:

// hello.js
// 将需要引入的模块全部写入到数组中,然后传递参数进行调用
define(['a', 'b'], function(a, ,b){
 // do something

 return{
 hello : function(username){
  console.log( 'hello, '+username );
 }
 }
})

==========

// main.js
define(['./hello'], function(h){
 h.hello('wenzi');
})

也就是说,在AMD中,模块必须使用define定义,依赖通过函数参数传进来,这样的一个好处就是所有的依赖都能一目了然。

3. CMD与seajs

CMD规范是国内著名的玉伯大神提出来的,将就的就是就近依赖,什么时候用到,就在那个地方进行require。SeaJS就是使用的CMD规范:

// hello.js
define(function(require, exports, module){
 var a = require('a');
 // do a

 var b = require( 'b' );
 // do b

 module.exports.hello = hello; // 对外输出hello
})

从这里也能看到AMD和CMD的区别:

  1. AMD通常需要一次性引入全部的依赖,然后通过参数传递;而CMD则需要时才引入

不过,AMD也支持CMD这样的引入格式,但内部还是按照AMD的逻辑进行执行。

4. 总结

这篇文章里介绍了下CommonJS, AMD, CMD规范的相关区别与联系,这里再简要的总结下:

  1. CommonJS: 每个文件就是一个模块,不用define进行定义,node使用此规范;
  2. AMD: 使用define定义一个模块,讲究提前依赖;
  3. CMD: 使用define定义模块,将就就近依赖

好了,以上就是这篇文章的全部内容了,接下来,我们就要开始正式进行node的学习了。感兴趣的朋友们请继续关注三水点靠木哦。

Javascript 相关文章推荐
jquery easyui的tabs使用时的问题
Mar 23 Javascript
查看源码的工具 学习jQuery源码不错的工具
Dec 26 Javascript
javascript 事件处理程序介绍
Jun 27 Javascript
javascript全局变量封装模块实现代码
Nov 28 Javascript
js substring从右边获取指定长度字符串(示例代码)
Dec 23 Javascript
基于jquery实现的可编辑下拉框实现代码
Aug 02 Javascript
学习JavaScript鼠标响应事件
Dec 25 Javascript
js canvas仿支付宝芝麻信用分仪表盘
Nov 16 Javascript
Vue from-validate 表单验证的示例代码
Sep 26 Javascript
Vue 实现从文件中获取文本信息的方法详解
Oct 16 Javascript
vue中v-for循环选中点击的元素并对该元素添加样式操作
Jul 17 Javascript
动态规划之使用备忘录来改进Javascript函数
Apr 07 Javascript
JS获得一个对象的所有属性和方法实例
Feb 21 #Javascript
JS中实现函数return多个返回值的实例
Feb 21 #Javascript
基于JS实现9种不同的面包屑和分布式多步骤导航效果
Feb 21 #Javascript
详解Angular.js指令中scope类型的几种特殊情况
Feb 21 #Javascript
bootstrap PrintThis打印插件使用详解
Feb 20 #Javascript
jQuery实现文档树效果
Feb 20 #Javascript
js以及jquery实现手风琴效果
Apr 17 #Javascript
You might like
php学习之数据类型之间的转换介绍
2011/06/09 PHP
php _autoload自动加载类与机制分析
2012/02/10 PHP
Laravel 6.2 中添加了可调用容器对象的方法
2019/10/22 PHP
Array.prototype.slice 使用扩展
2010/06/09 Javascript
jQuery 写的简单打字游戏可以提示正确和错误的次数
2014/07/01 Javascript
javascript文件加载管理简单实现方法
2015/07/25 Javascript
JS/jQ实现免费获取手机验证码倒计时效果
2016/06/13 Javascript
jQuery mobile的header和footer在点击屏幕的时候消失的解决办法
2016/07/01 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
纯js实现隔行变色效果
2017/11/29 Javascript
vue2.0 路由不显示router-view的解决方法
2018/03/06 Javascript
JS实现前端页面的搜索功能
2018/06/12 Javascript
jQuery实现表单动态添加数据并提交的方法
2018/07/19 jQuery
Vue利用History记录上一页面的数据方法实例
2018/11/02 Javascript
Vue组件的使用及个人理解与介绍
2019/02/09 Javascript
layui 数据表格复选框实现单选功能的例子
2019/09/19 Javascript
[04:29]DOTA2亚洲邀请赛小组赛第一日 TOP10精彩集锦
2015/02/01 DOTA
[19:26]TNC vs EG (BO3)
2018/06/07 DOTA
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
2014/06/10 Python
Python中time模块和datetime模块的用法示例
2016/02/28 Python
Python编程中归并排序算法的实现步骤详解
2016/05/04 Python
pycharm 实现显示project 选项卡的方法
2019/01/17 Python
python 为什么说eval要慎用
2019/03/26 Python
python中selenium操作下拉滚动条的几种方法汇总
2019/07/14 Python
Python搭建Keras CNN模型破解网站验证码的实现
2020/04/07 Python
python 多进程和协程配合使用写入数据
2020/10/30 Python
python 基于selenium实现鼠标拖拽功能
2020/12/24 Python
Java程序开发中如何应用线程
2016/03/03 面试题
大学生军训自我评价分享
2013/11/09 职场文书
音乐学个人的自荐书范文
2013/11/26 职场文书
数控专业个人求职信范文
2014/02/05 职场文书
安全标语口号
2014/06/09 职场文书
关于运动会广播稿200字
2014/10/08 职场文书
劳动者解除劳动合同通知书
2015/04/16 职场文书
vue backtop组件的实现完整代码
2021/04/07 Vue.js
python 机器学习的标准化、归一化、正则化、离散化和白化
2021/04/16 Python