前言

想开始编写Node.js代码,那么我们就必须先熟悉它的模块化规范CommonJS,本文将详细讲解CommonJS规范

本文代码 >>> github 地址

CommonJS

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

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

【特点】

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

新建文件example.js

// example.js
var x = 5;
var addX = function (value) {
return value + x;
};

上面代码中,变量x和函数addX,是当前文件example.js私有的,其他文件不可见。

如果想在多个文件分享变量,必须定义为global对象的属性。

global.warning = true;

上面代码的warning变量,可以被所有文件读取。当然,这样写法是不推荐的。

module.exports

CommonJS规范规定,每个模块内部,module变量代表当前模块。

这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。

加载某个模块,其实是加载该模块的module.exports属性。

新建文件02_module.js

console.log('module');

const NUM = 100;

function test (){
console.log(NUM);
} // 输出常量
module.exports.num = NUM;
// 输出函数
module.exports.testFn = test;

exports 与 module.exports

它们之间是一层引用关系,exports 引用了 module.exports对象

06_exports.js

console.log(exports,module.exports); // {} , {}
exports.num = '100';
console.log(exports,module.exports); // { num: '100' } { num: '100' }

看上面的代码的输出可以证明exports 引用了 module.exports。那么之前我们采用module.exports输出的内容,其实可以简写为exports输出

【错误的做法】

exports = {
a:1,
b:2
};

上面代码会切断 exports 对 module.exports的引用关系。导致输出的文件,在其它文件是无法使用的

[注意]建议还是使用module.exports规范些,不会产生额外的错误!

require

require方法用于加载模块。

新建文件 03_require.js

const m1 = require('./02_module');

m1.testFn();

执行命令:

node 03_require.js

运行结果:

【路径】

[1] / 表示绝对路径,./ 表示相对于当前文件的路径,

[2] 不写路径则认为是 build-in模块或者各级 node_modules内的第三方模块

const m1 = require('./02_module.js'); // 这样就会在同级目录中寻找02_module.js文件
const m = require('02_module.js'); // 这样只会去 node_modules去寻找相应的文件

【加载文件】

[1]支持js、json、node 拓展名,不写依次尝试加载

const m1 = require('./02_module'); // 这样会在同级目录中寻找 是否有02_module.js 的文件如果有则加载,如果没有则去寻找是否有02_module.json 或者 02_module.node 文件

【特性】

[1]module 被加载的时候执行,加载后缓存

创建文件 04_catch.js

>>> 当我们连续两次引入同一个文件其实只会执行一次

const m1 = require('./02_module');
const m2 = require('./02_module');
// 同时引入两次 02_module文件

我们执行命令 :node 04_catch.js,输出结果:

[2]一旦出现某个模块被循环加载,就只输出已执行的部分,还未执行的部分不会输出

// 1、创建文件:05_modA.js
module.exports.test = 'A'; const modB = require('./05_modB');
console.log('modA: ', modB.test); module.exports.test = 'AA'; // 2、创建文件:05_modB.js
module.exports.test = 'B'; const modA = require('./05_modA');
console.log('modB: ', modA.test); module.exports.test = 'BB'; // 3、创建文件:05_main.js
const modA = require('./05_modA');
const modB = require('./05_modB');

我们可以看到 modA中引入modB,modB中也引入了modA,它们形成了循环引用。那么此时执行 node 05_main.js 会输出什么呢?

其实就是遵循上诉原理:一旦出现某个模块被循环加载,就只输出已执行的部分,还未执行的部分不会输出。大家可以动起手来敲敲代码很好理解的。

[注意]平时写代码的时候切记要避免循环引用

Node.js实战项目学习系列(3) CommonJS 模块化规范的更多相关文章

  1. Node.js实战项目学习系列(1) 初识Node.js

    前言 一直想好好学习node.js都是半途而废的状态,这次沉下心来,想好好的学习下node.js.打算写一个系列的文章大概10几篇文章,会一直以实际案例作为贯穿的学习. 什么是node Node.js ...

  2. Node.js实战项目学习系列(2) 开发环境和调试工具

    前言 上一节让我们对Node.js有一个初步的了解,那么现在可以开始正式学习下Node.js的开发了,但是任何一门语言要设计到开发,就必须先学习开发环境以及调试.本文将主要讲解这些内容. 本文涉及到的 ...

  3. Node.js实战项目学习系列(4) node 对象(global、process进程、debug调试)

    前言 在之前的课程我们学习了Node的模块化规则,接下来我们将学习下 Node的几个新特性:global ,process进程,debug调试 global 跟在浏览器中的window一样都是全局变量 ...

  4. Node.js实战项目学习系列(5) node基础模块 path

    前言 前面已经学习了很多跟Node相关的知识,譬如开发环境.CommonJs,那么从现在开始要正式学习node的基本模块了,开始node编程之旅了. path path 模块提供用于处理文件路径和目录 ...

  5. iKcamp团队制作|基于Koa2搭建Node.js实战项目教学(含视频)☞ 环境准备

    安装搭建项目的开发环境 视频地址:https://www.cctalk.com/v/15114357764004 文章 Koa 起手 - 环境准备 由于 koa2 已经开始使用 async/await ...

  6. 前端(Node.js)(3)-- Node.js实战项目开发:“技术问答”

    1.Web 与 Node.js 相关技术介绍 1.1.Web应用的基本组件 web应用的三大部分 brower(GUI)<==>webserver(business logic.data ...

  7. 开始连载啦~每周2更共11堂iKcamp课|基于Koa2搭建Node.js实战项目教学(含视频)| 课程大纲介绍

  8. Node.js 实战 & 最佳 Express 项目架构

    Node.js 实战 & 最佳 Express 项目架构 Express Koa refs https://github.com/xgqfrms/learn-node.js-by-practi ...

  9. 《Node.js实战(双色)》作者之一——吴中骅访谈录

随机推荐

  1. LeetCode算法题-Fibonacci Number(Java实现)

    这是悦乐书的第250次更新,第263篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第117题(顺位题号是509).Fibonacci数字,通常表示为F(n),形成一个称为 ...

  2. 读写锁ReentrantReadWriteLock的使用

    package com.thread.test.Lock; import java.util.Random; import java.util.concurrent.locks.Lock; impor ...

  3. linux ssh免密登陆远程服务器

    10.170.1.18服务器免密登录到10.170.1.16服务器 首先登入一台linux服务器(10.170.1.18),此台做为母机(即登入其他linux系统用这台做为入口):执行一行命令生成ke ...

  4. idea右键无法新建Java Class

    项目中新建目录之后,要在该目录下新增java Class文件,右键——>New发现无对应选项. 原因:新建目录之后需要设置目录作用,从而让idea识别. 方法:File-Project Stru ...

  5. iOS开发基础篇-Button基础

    一.简单介绍  UIButton 的功能:响应用户操作.显示文字.显示图片.调整内部图片和文字的位置. 二. UIButton 的状态  UIControlStateNormal :普通状态,为默认情 ...

  6. Spring+SpringMVC+Hibernate小案例(实现Spring对Hibernate的事务管理)

    原文地址:https://blog.csdn.net/jiegegeaa1/article/details/81975286 一.工作环境 编辑器用的是MyEclipse,用Mysql数据库,mave ...

  7. python之yagmail模块--小白博客

    yagmail 实现发邮件 yagmail 可以简单的来实现自动发邮件功能. 安装 pip install yagmail 简单例子 import yagmail #链接邮箱服务器 yag = yag ...

  8. DOTween的Sequence图例说明

  9. CodeForces Round #553 Div2

    A. Maxim and Biology 代码: #include <bits/stdc++.h> using namespace std; int N; string s; int mi ...

  10. CodeVs 1615 数据备份

    题目:数据备份 链接:Here 题意:有n个点在一条线上,每次连线可以连接两个点(每个点只能被连一次),要求找出m个连线,他们的和最小(连线权值就是两点距离),输出最小的和.给出n.m和每个点的坐标. ...