Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型,使其轻量又高效。 Node.js 的包管理器 npm,是全球最大的开源库生态系统。
1.1. 环境搭建
Node.js 下载地址: https://nodejs.org/
安装完成后,在命令行窗口输入 node -v
,即可看到版本信息,在命令行输入 node
,可进入Node.js 交互环境,在交互环境下,你可以输入任意 JavaScript 语句,例如 100+200,回车后将得到输出结果。要退出 Node.js 环境,连按两次 Ctrl+C
。
1.2. npm
npm 是 Node.js 的包管理工具(package manager)。我们在 Node.js 上开发时,会用到很多别人写的 JavaScript 代码。如果我们要使用别人写的某个包,每次都根据名称搜索一下官方网站,下载代码,解压,再使用,非常繁琐。于是一个集中管理的工具应运而生:大家都把自己开发的模块打包后放到 npm 官网上,如果要使用,直接通过 npm 安装就可以直接用,不用管代码存在哪,应该从哪下载。
更重要的是,如果我们要使用模块A,而模块A又依赖于模块B,模块B又依赖于模块X和模块Y,npm 可以根据依赖关系,把所有依赖的包都下载下来并管理起来。
npm 已经在 Node.js 安装的时候顺带装好了。我们在命令提示符或者终端输入npm -v
,即可以看到 npm 的版本。
npm 使用场景
- 用户从NPM服务器下载别人编写的第三方包到本地使用。
- 用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
- 用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
1.2.1. npm安装模块
npm install express # 本地安装
npm install express -g # 全局安装
如果出现错误:npm err! Error: connect ECONNREFUSED 127.0.0.1:8087
,解决办法:
npm config set proxy null
1.2.2. npm卸载模块
$ npm uninstall express
1.2.3. npm更新模块
$ npm update express
1.2.4. npm搜索模块
$ npm search express
1.2.5. HelloWorld
新建一个文件 hw.js ,然后在命令行窗口下进入该目录,输入命令 node hw.js
,即可执行 hw.js 里面的代码。
console.log('HelloWorld');
1.3. 模块 module
为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在 Node 环境中,一个 .js 文件就称之为一个模块(module)。使用模块还可以避免函数名和变量名冲突。相同名字的函数和变量完全可以分别存在不同的模块中,因此,我们自己在编写模块时,不必考虑名字会与其他模块冲突。 模块名其实就是 .js 的文件名,比如 hello.js 文件就是名为 hello 的模块。
1.3.1. 定义module
'use strict';
function greet(name) {
console.log('Hello, ' + name + '!');
}
module.exports = greet;
函数 greet() 是我们在 greet 模块中定义的,最后一行是一个赋值语句,它的意思是,把函数 greet 作为模块的输出暴露出去,这样其他模块就可以使用 greet 函数了。
1.3.2. 使用module
'use strict';
// 引入greet模块:
var greet = require('./greet');
var s = 'a284628487';
greet(s); // Hello, a284628487!
引入 hello 模块用 Node 提供的 require 函数。
引入的模块作为变量保存在 greet 变量中,变量 greet 就是在 greet.js 中我们用module.exports = greet; 输出的 greet 函数。所以,main.js 就成功地引用了 greet.js 模块中定义的 greet() 函数,接下来就可以直接使用它了。
在使用 require() 引入模块的时候,请注意模块的相对路径。因为 main.js 和 hello.js 位于同一个目录,所以我们用了当前目录 .。
var greet = require('./greet'); // 不要忘了写相对目录!
如果只写模块名:
var greet = require('greet');
则 Node 会依次在内置模块、全局模块和当前模块下查找 hello.js ,很可能会得到一个错误:
module.js
throw err;
^
Error: Cannot find module 'greet'
at Function.Module._resolveFilename
at Function.Module._load
...
at Function.Module._load
at Function.Module.runMain
遇到这个错误,通常按如下排查错误: 模块名是否写对了; 模块文件是否存在; 相对路径是否写对了;
1.3.3. exports
exports可以输出任意的对象,可以是任意的对象、函数、数组、变量等等。
输出变量
module.exports = variable;
输出对象
function eat(food){
console.log('eat ' + food);
}
function greet(name) {
console.log('Hello, ' + name + '!');
}
module.exports = {
greet: greet,
eat: eat
}
使用输出的多个变量
var greet = require('./greet');
var s = 'a284628487';
greet.greet(s); // Hello, a284628487!
greet.eat('food'); // eat food
1.4. CommonJS 规范
module模块加载机制被称为 CommonJS 规范。在这个规范下,每个 .js 文件都是一个模块,它们内部各自使用的变量名和函数名都互不冲突,例如,hello.js 和 main.js 都申明了全局变量 var s = 'xxx'
,但互不影响。
一个模块想要对外暴露变量(函数也是变量),可以用 module.exports = variable
;,一个模块要引用其他模块暴露的变量,用 var ref = require('module_name');
就拿到了引用模块的变量。