nodejs入门之CommonJS规范

CommonJS规范

1.概述

Node 应用由模块组成,采用 CommonJS 模块规范。

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

​ CommonJS规范规定,每个模块内部,module变量代表当前模块,这个变量是一个对象,它的exports属性(module.exports)是对外的接口,加载某个模块,其实就是加载该模块的module.exports属性

​ require方法用于加载模块

​ CommonJS模块特点如下:

​ 1.所有代码都运行在模块作用域,不会污染全局作用域

​ 2.模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后 再加载,就直接读取缓存结果,要想让模块再次运行,必须清除缓存

​ 3.模块加载顺序,按照其在代码中出现的顺序.

​ 4.模块加载是同步的,也就是说只有加载完成,才能执行后面的操作

2.module对象

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

  • module.id 模块的识别符,通常是带有绝对路径的模块文件名

  • module.filename 模块的文件名,带有绝对路径

  • module.loaded 返回一个布尔值,表示模块是否已经完成加载

  • module.parent 返回一个对象,表示调用该模块的模块

  • module.children 返回一个数组,表示该模块要用到的其他模块

  • module.exports 表示对外输出的值

    我们在当前一个js中直接输出console.log(module);会输出这样一个module对象.

    { id: '.',
      exports: { '$': [Function] },
      parent: null,
      filename: '/path/to/index.js',
      loaded: false,
      children:
       [ { id: '/path/to/node_modules/jquery/dist/jquery.js',
           exports: [Function],
           parent: [Circular],
           filename: '/path/to/node_modules/jquery/dist/jquery.js',
           loaded: true,
           children: [],
           paths: [Object] } ],
      paths:
       [ '/home/user/deleted/node_modules',
         '/home/user/node_modules',
         '/home/node_modules',
         '/node_modules' ]
    }
    

module.exports

module.exports属性表示当前模块对外输出的接口,其他文件加载该模块,实际上是读取module.exports

//idnex.js
var num=3;
function add(a,b){
    return a+b;
}

module.exports={
    add:add
}

//此处输出跟上面效果一样,这是es6,对象的简写,key,value一致,可以只写一个
moudle.exports={
    add
}

//这种方式也是可以的
module.exports.add=add;//暴露方法
module.exports.num=num;//暴露变量

//在同目录下的main.js 中
var example=require('./index');
example.add(1,2);  //3

exports变量

每个模块化还提供一个exports变量,指向module.exports,这就等于在每个模块头部,都有一行隐藏的如下代码

var exports=module.exports;

例如: exports.show=function(){console.log(123)}

注意:不能把exports直接指向一个值,这样就相当于切断了exports和module.exports的关系

例如:exports=10;

如果你觉得,exports与module.exports之间的区别很难分清,一个简单的处理方法,就是放弃使用exports,只使用module.exports

3.AMD规范与CommonJS规范的兼容性

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。

4.require命令

1.基本用法

require命令的基本功能是,读入并执行一个javascript文件,然后返回该模块的module,exports对象,如果发现没有指定模块,会报错.

2.加载规则

  • 后缀名默认为.js
var show=require('show')
//等同于
var show=require('show.js')
//.js可以省略
  • 如果参数字符串以“/”开头(linux)或者以 “D:/”盘符开头(windows),则表示加载的是一个位于绝对路径的模块文件。比如,require(’/home/marco/foo.js’) 将加载 /home/marco/foo.js

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

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

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

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

3.目录的加载规则

通常,我们会把相关的文件会放在一个目录里面,便于组织。这时,最好为该目录设置一个入口文件,让 require 方法可以通过这个入口文件,加载整个目录。

在目录中放置一个 package.json 文件,并且将入口文件写入 main 字段。下面是一个例子。

// package.json
{ 
  "name" : "some-library",
  "main" : "./lib/some-library.js" 
}

require 发现参数字符串指向一个目录以后,会自动查看该目录的 package.json 文件,然后加载 main 字段指定的入口文件。如果 package.json 文件没有 main 字段,或者根本就没有 package.json 文件,则会加载该目录下的index.js 文件 或者 index.json 文件 或者 index.node 文件。

4.模块的加载机制

CommonJS模块的加载机制是:输出拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值,上代码了解一下:

//index.js
var num=1;
function add(){
    num++;
}

module.exports={
    num:num,
    add:add
}

现在呢,我们引入这个index.js

//main.js
var num=require("./index").num;
var add=require("./index").add;

console.log(num);//3
add();
console.log(num);//3

上述代码说明,num输出以后,index.js模块内部的变化不会影响到咱们这边调用时的num了

此文参考阮一峰大神文章

发布了17 篇原创文章 · 获赞 40 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/liuqiao0327/article/details/105071343