Node.js 学习笔记

node.js.logo

最近在学习Node.js,以下是鄙人的学习笔记。因为从未深入了解过js,有什么错误希望大家指出。


Node.js

Node.js® is a JavaScript runtime built on Chrome’s V8 JavaScript engine.
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。

Node.js 并不是一门新语言,而是一个基于 Chrome V8 引擎的js 运行环境。就像JVM运行java的程序一样,Node.js 的功能是运行JavaScript程序。不要误以为只是运行的在服务端的JavaScript,其API 与浏览器端的API 也是有一部分差别的,例如Node.js 不包括 DOM 和 BOM。

Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.
Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。

  • 事件驱动(I/O操作等异步操作结束后通知总线程)
  • 非阻塞I/O(磁盘读写都是异步操作,不会阻塞总线程)


Node.js 工作模型

Node.js’ package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
Node.js 的包管理器 npm,是全球最大的开源库生态系统。

npm是随同Node.js一起安装的包管理工具,能解决Node.js代码部署上的很多问题,常见的使用场景有以下几种:

  • 允许用户从npm服务器下载别人编写的第三方包到本地使用。
  • 允许用户从npm服务器下载并安装别人编写的命令行程序到本地使用。
  • 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。

类似于 Ubuntu 的 apt、Centos 的 yum

CommonJS

1. 产生的背景

js没有模块系统、标准库较少、缺乏包管理工具;
为了让js可以在任何地方运行,以达到Java、C#、PHP这些后台语言具备开发大型应用的能力。

类似Java中的类,区别在于 CommonJS规定一个js文件只能定义一个模块。

2. CommonJS规范

一个文件就是一个模块,拥有单独的作用域;
普通方式定义的变量、函数、对象都属于该模块内;
通过require来加载模块;
通过exports和modul.exports来暴露模块中的内容。

基本与java类中一致的思想,一个文件中的变量为这个模块的成员变量,方法为模块的成员方法。require 有点像 import,更像 new 一个对象。exports 可以类比为java 中的 private 和 public,限制了模块内部内容的访问权限,未exports 的内容默认是 private 的 只能内部调用,并不能在外部 被require 之后调用。

02_cusmod.js

console.log('This is a module');
const testvar = 100;
var test = function () {
    console.log(testvar);
}
module.exports.testVar = testvar;
module.exports.testFn = test; 

03_require.js

const mod = require('./02_cusmod');
console.log(mod.testVar);
mod.testFn();

03_require 运行结果

This is a module
100
100

02_cusmod.js 随便定义了一个模块有一个成员变量,一个方法,一个输出语句,可见exports 导出后的内容可以在其他的模块中被调用,而且被require 时 会执行相应的模块代码。


所有代码都运行在模块作用域,不会污染全局作用域;
模块可以多次加载,但只会在第一次加载的时候运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果;
模块的加载顺序,按照代码的出现顺序是同步加载的。

04_cache.js

const mod1 = require('./02_cusmod');
const mod2 = require('./02_cusmod');
console.log(mod1.testVar);
mod1.testFn();
console.log(mod2.testVar);
mod2.testFn();

04_cache 执行结果

This is a module
100
100
100
100

可见其结果只有一个 This is a module 则表明 只在第一个 require('./02_cusmod') 时执行 02_cusmod 中的代码,并且对代码进行缓存,后面再执行require 都是从缓存中提取的。


当模块间出现循环依赖时,只会显示已加载的内容

循环依赖就是a文件中require b文件,然后b文件中又反过来require a文件。这个问题我们平时可能并不大注意到,但如果处理不好可能会引起一些让人摸不清的问题。所以项目中最好不要出现循环依赖。

05_modA.js

module.exports.test = 'A';
const modB = require('./05_modB');
console.log('modA:',modB.test);
module.exports.test = 'AA';

05_modB.js

module.exports.test = 'B';
const modA = require('./05_modA');
console.log('modB:',modA.test);
module.exports.test = 'BB';

05_main.js

const modA = require('./05_modA');
const modB = require('./05_modB');
console.log(modA.test);
console.log(modB.test);

05_main.js 执行结果

modB: A
modA: BB
AA
BB

由结果和代码可知, 当遇到这种循环依赖时,由于require 是同步阻塞型的操作,所以在modB中输出的是A 而不是 AA 因为在require modB时 modA中的 test还是 A 并没有执行 到 module.exports.test = 'AA'; 而在require 完成之后 所有代码都加载完毕,再输出的时候显示 已经是 AA。





未完待续

猜你喜欢

转载自blog.csdn.net/qq_33472557/article/details/80228829