commonjs简介

学习一门技术,基础是关键,比如想学react或redux,那就得有node和webpack的基础;学习webpack,知道commonjs规范,理解起来才会更快 。所谓万丈高楼平地起,基础打牢了,理解知识点才会更透彻,后期提升才会更快。

nodejs和commonjs区别?

commonjs是规范,nodejs是这种规范的实现。
commonjs还在不断的发展,还会有新的东西往里添加。

CommonJs有很多实现,其中不乏大名鼎鼎的项目,比如说Apache的CouchDBnode.js
这些项目大部分只实现CommonJs的部分规范。

CommonJs概述

每个文件就一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

私有作用域不会污染全局作用域。
模块可加载多次,只会在第一次加载时运行一次,然后结果会被缓存起来,以后在使用,就直接读取缓存结果。想要让模块再次运行,必须清除缓存
模块加载顺序是按照其在代码中出现的顺序

基本使用

1、输出:module对象。
使用module.exports输出一个变量或函数,也可以使用exports输出

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

module是可以省略的。
2、module对象
node内部提供一个module构建函数。每个模块内部,都有一个module对象,代表当前模块,他有一些自身属性

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

3、exports变量
node为么每个模块提供一个exports变量,指向module.exports

exports.area = function(r){console.log(r)}
这个是ok的。

exports = function(r){console.log(r)}
这个写法无效,因为改变了改变了exports的指向

如果一个文件中 module.exports 被重新赋值,该文件中其他exports出去的变量(属性)也是无效的。

说说加载

上面说了输出(module.exoprts、exports),接下来说说载入。
node采用CommonJS规范。内置require命令用于加载模块:var foo = require("filename")

加载规则

说说require内部处理流程
1、在加载前,检查是否有缓存(module._cache)
2、如果缓存之中没有,就创建一个新的module实例
3、将他缓存起来
4、使用module.load()加载指定模块文件;读取文件内容之后,使用module.compile()执行文件代码
5、如果加载/解析过程报错,就从缓存删除该模块
6、返回该模块的module.exports

第一步是加载文件的规则
一般后缀默认为.js

路径分三种情况
1、('/home/app.js') -->绝对路径
2、('./home/app.js') -->相对路径 (当前路径下的home文件夹下的appjs文件)
3、('react') --> 没有 以 ‘./ 和 /’开头的路径,则表示加载的一个默认提供的核心模块,会去node_modules文件夹下找或node的系统安装目录中找

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

模块缓存
第一次加载某个模块,node会缓存该模块,以后再次加载会直接从缓存中取出该模块的module.exports属性
删除执行模块
delete require.cache[moduleName]

AMD规范与CommonJS的区别

CommonJS加载模块是同步的,加载完才执行后续操作;
AMD是异步加载模块,允许指定回调函数。
nodejs用于服务器端,代码文件一般都在本地硬盘,加载比较快,适合使用CommonJS,而浏览器环境,要从服务器加载模块,比较慢,所以浏览器一般采用AMD规范。

为什么会有规范?

回答这个问题之前得知道为什么要有模块?

因为有了模块,我们就可以很方便的使用别人的代码,想要什么功能,就加载什么模块,这样带来了一个问题大家得按照相应的方式编写模块,不然每个人写自己风格的代码,岂不是乱套了。

所有才有了CommonJS、AMD、CMD这些规范!

再说说AMD规范

全称:异步模块定义

诞生背景:基于commonJS规范的nodeJS出来以后,服务端的模块概念已经形成,很自然地,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。但是,由于一个重大的局限,使得CommonJS规范不适用于浏览器环境。
同步加载对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。
因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。

AMD实现库有 require.jscurl.js
requirejs主要解决两个问题:
1、实现js文件的异步加载,避免页面因为js文件加载失去响应
2、管理模块之间的依赖性,便于代码的编写和维护

AMD模块的写法

模块必须使用define函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。
例子:

   // 没有依赖其他模块
   //math.js
   define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });
   // 加载方法(这是没有)
    require(['math'], function (math){
    alert(math.add(1,1));
   });

  //如果依赖其他模块
  define(['myLib'], function(myLib){
    function foo(){
      myLib.doSomething();
    }
    return {
      foo : foo
    };
 });
// 会先加载myLib模块

还可以加载非规范的模块
使用require.config方法,定义他们的一些特征
例子:

   // underscore和backbone这两个库,都没有采用AMD规范编写。如果要加载它们的话,必须先定义它们的特征。
    require.config({
    shim: {

      'underscore':{
        exports: '_'
      },
      'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      }
    }
  });

另外还有CMD,玉伯写的seajs,就是遵循他提出的CMD规范。

总结

  • 为什么要有规范?
    因为要模块化。

  • 为什么要模块化?
    因为现在项目越来越大,按照功能划分,使用的时候直接加载相应的模块即可,利于维护和开发。比如nodejs都可以做服务器端语言了,将来项目肯定会越来越大,越来越复杂(个人认为:node将来会向java、Python这个方向发展的)。项目划分清晰明了

  • 为什么现在有那么多规范?(CommonJS、AMD、CMD)
    因为不同规范适用于不同的场景。
    CommonJS是同步加载,很快能得到结果的可以使用这个方式。比如:node加载文件时是在本地硬盘加载的,肯定快。
    AMD、CMD是异步加载,获取结果比较慢的的情况可以使用这种方式,因为它可以设置回调,什么时候加载完成,什么时候执行对调。比如:浏览器加载服务器的数据,这个受网络环境影响很大,不能一直等服务器返回结果。所以可以给个回调方法,什么时候有结果了,走回调即可。

第一次写这么长的文章,肯定有很多值得商榷的地方,以后好好努力

参考文献:
什么是CommonJS? - 依水间 - 博客园
js模块化编程之彻底弄懂CommonJS和AMD/CMD!
CommonJS规范 -- JavaScript 标准参考教程(alpha)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容