Web前端 之 CommonJS 模块化规范与Node实现

来源:互联网 发布:职工工资管理系统c语言 编辑:程序博客网 时间:2024/05/08 06:13

前言

上一篇文章中,我们主要介绍了AMD规范的实现RequireJS对前端模块化做出的努力,RequireJS更适合前端的JavaScript,而CommonJS更适合作为后端脚本的JavaScript,所以RequireJS在浏览器端的应用非常火热,并且名噪一时,而作为后端JavaScript的代表Node则遵循CommonJS规范。这篇文章中,我们谈谈经常和AMD一起提到并比较的CommonJS规范,node遵循CommonJS规范,并结合Node实现模块化实例,讲解CommonJS对于模块化管理的思想和实践。


CommonJS规定三个模块化编程相关的机制,module对象、require函数和exports对象。exports则定义模块导出的出口,require则是引用外部其他模块,module代表模块本身,exports对象其实是module的子属性对象。因为module对象具有模块全局性,所以在模块导出时写module.exports或者只写exports是一样的,就像浏览器中document对象是window对象的子属性对象,因为window具有全局性,可以直接书写document而不必是window.document


Node定义模块

在CommonJS规范下定义类或模块不需要特殊的包裹,至少表面上是这样的,而事实上,比如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有编译JavaScript模块的过程,因此将模块的上下文信息注册,这样就不用我们手动包裹(如在Requirejs中使用的define)。下面我们定义一个示例类,纯示例,大家不要纠结设计哈。


/** * Description: 菜系类 * Author: 庆祝亚运会 * Date: 2016-06-23 */function ShuiZhuFish(){  this.name = "水煮鱼";  this.huohou = "小火慢炖";  this.remark = "非常有名的一道菜";}ShuiZhuFish.prototype.getName = function () {  return this.name;};ShuiZhuFish.prototype.setName = function (name) {  this.name = name;};module.exports = ShuiZhuFish;


通过exports对象,我们就导出了模块类“ShuiZhuFish”,注意我们导出的是一个类,而不是一个方法或者对象,我们将exports直接赋值为类,这样我们可以在引用该模块的文件中直接使用new关键字来实例化该类,此时我们需要带上module,而不能只是使用exports。接下来我们将定义模块的文件命名为“ShuiZhuFish.js”,并在实际的程序中引用。


node引用模块

我们在“ShuiZhuFish”类同目录新建文件,使用require引用,注意当使用require函数引用文件时,路径查找的问题,如果require只是指定文件名,没有指定相对路径,如“./”或者“../”,node首先会尝试缓存中加载,然后尝试从package.json中路径相关的规定加载,最后从预先规定的路径中查找。如果写了相对路径符号,就不会有这么多的过程;还有就是如果不加扩展名,如.js,就会判断是否是js、json等文件类型。如果在require时预先制定好这些变数,那么载入模块就会很快。


var ShuiZhuFish = require('./ShuiZhuFish.js');var dish = new ShuiZhuFish();console.log(dish.getName());

将文件命名为main.js,打开命令行运行:


运行结果


总结

本文介绍了遵循commonjs规范的node的模块实现,好的,就写到这里。

1 0
原创粉丝点击