目录
向外共享模块作用域中的成员:module 对象/module.exports 对象
前言:
命令行
命令行窗口(cmd窗口、终端、shell)
win+r 运行cmd回车进入命令行窗口。
常用指令:
- dir 列出当前目录下的所有文件,
- cd 目录名 进入到指定目录( 目录 . 代表当前目录 .. 代表上一级目录)
- md 目录名 创建目录
- rd 目录名 删除目录
- cd 退回到根目录
- del 删除文件
- exit 退出dos 命令行
当在命令行窗口打开一个文件,或一个程序时,系统会首先在当前目录下寻找文件程序,找到了直接打开没找到则到环境变量path的路径中寻找,直到找到为止。(因此可以将常用的程序或者文件路径添加到path中,方便后续使用)
进程和线程
进程负责为程序的运行提供必备的环境,线程是计算机的最小计算单位,线程负责执行进程中的程序;
node简介
Node.js 是一个开源和跨平台的 JavaScript 运行时环境。Node.js 应用程序在单个进程中运行,无需为每个请求创建新的线程。在 Node.js 中,可以毫无问题地使用新的 ECMAScript 标准。
node是一个可以在服务器端运行JavaScript的开发源代码、跨平台JavaScript运行环境。
运行node.js
node
命令是用来运行 Node.js 脚本的命令
运行 Node.js 程序的常用方法是:运行全局可用的命令 node +
要执行的文件的名称。
例如:node app.js (当运行命令时,请确保您位于包含 app.js
文件的同一目录中。)
按下 tab
键,则 REPL 会尝试自动补全所写的内容,以匹配已定义或预定义的变量。
试输入 JavaScript 类的名称,例如 Number
,添加一个点号并按下 tab
。REPL 会打印可以在该类上访问的所有属性和方法。
输入 global.
并按下 tab
,可以检查可以访问的全局变量。
当在控制台中运行程序时,可以用 ctrl-C
关闭它,以编程方式退出可以使用:process.exit()
。
可以传入一个整数,向操作系统发出退出代码的信号:process.exit(1) 默认的退出码为 0
,表示成功。也可以设置 process.exitCode
属性:process.exitCode = 1 当程序结束时,Node.js 将返回该退出代码。
还有一些点命令:
.help
: 显示点命令的帮助。.editor
: 启用编辑器模式,可以轻松地编写多行 JavaScript 代码。当处于此模式时,按下 ctrl-D 可以运行编写的代码。.break
: 当输入多行的表达式时,输入.break
命令可以中止进一步的输入。相当于按下 ctrl-C。.clear
: 将 REPL 上下文重置为空对象,并清除当前正在输入的任何多行的表达式。.load
: 加载 JavaScript 文件(相对于当前工作目录)。.save
: 将在 REPL 会话中输入的所有内容保存到文件(需指定文件名)。.exit
: 退出 REPL(相当于按下两次 ctrl-C)。
Node.js 从命令行接收参数
参数可以是独立的,也可以具有键和值。
node app.js joe
// 或
node app.js name=joe
获取参数值的方法是使用 Node.js 中内置的 process
对象。它公开了 argv
属性,该属性是一个包含所有命令行调用参数的数组。
- 第一个参数是
node
命令的完整路径。 - 第二个参数是正被执行的文件的完整路径。
- 所有其他的参数从第三个位置开始。
// 使用循环迭代所有的参数(包括 node 路径和文件路径):
process.argv.forEach((val, index) => {
console.log(`${index}: ${val}`)
})
// 也可以通过创建一个排除了前两个参数的新数组来仅获取其他的参数:
const args = process.argv.slice(2)
// 如果参数没有索引名称,例如:
node app.js joe
// 则可以这样访问:
const args = process.argv.slice(2)
args[0]
exports
Node.js 具有内置的模块系统。
Node.js 文件可以导入其他 Node.js 文件公开的功能。
// 当想要导入某些东西时,使用
const library = require('./library')
// 可以导入存在于当前文件夹中的 library.js 文件中公开的功能。
在这之前必须先公开功能,然后其他文件才能将其导入。这就是module 系统提供的 module.exports
API 可以做的事。
//第一种方式是将对象赋值给 module.exports(这是模块系统提供的对象),这会使文件只导出该对象: // JS const car = { brand: 'Ford', model: 'Fiesta' } module.exports = car //在另一个文件中 const car = require('./car') //第二种方式是将要导出的对象添加为 exports 的属性。这种方式可以导出多个对象、函数或数据: // JS const car = { brand: 'Ford', model: 'Fiesta' } exports.car = car // 或直接 // JS exports.car = { brand: 'Ford', model: 'Fiesta' } // 在另一个文件中,则通过引用导入的属性来使用它: // JS const items = require('./items') items.car // 或 // JS const car = require('./items').car
module.exports
公开了它指向的对象;export
公开了它指向的对象的属性。
npm
npm
是 Node.js 标准的软件包管理器。npm
可以管理项目依赖的下载。
安装所有依赖:npm install
安装单个软件包:npm install <package-name>
卸载包:运行 npm uninstall 命令,来卸载指定的包
可以指定包安装的位置:
核心依赖包:--save
安装并添加条目到package.json
文件的 dependencies。(在开发和项目上线之后都需要用到)开发依赖包:--save-dev
安装并添加条目到package.json
文件的 devDependencies。(只在项目开发阶段会用到,在项目上线之后不会用到)简写: -D- -g 全局包,只有工具性质的包,才有全局安装的必要性。
更新软件包:npm update 会检查所有软件包是否有满足版本限制的更新版本。
列举当前目录下的安装包: npm list
获取最新版本的包:npm info 包名(详细信息)
检查包是否过时: npm outdated
全局安装:npm install 包名 -g
告知其在计算机上的确切位置: npm root -g
命令
在代码中使用它,则只需使用 require
将其导入到程序中
package.json 文件可以记录下载包的信息。
version
表明了当前的版本。name
设置了应用程序/软件包的名称。description
是应用程序/软件包的简短描述。main
设置了应用程序的入口点。private
如果设置为true
,则可以防止应用程序/软件包被意外地发布到npm
。scripts
定义了一组可以运行的 node 脚本。dependencies
设置了作为依赖安装的npm
软件包的列表。devDependencies
设置了作为开发依赖安装的npm
软件包的列表。engines
设置了此软件包/应用程序在哪个版本的 Node.js 上运行。browserslist
用于告知要支持哪些浏览器(及其版本)。
i5ting_toc 是一个可以把 md 文档转为 html 页面的小工具 :
fs文件系统模块
fs.readFile()方法,用来读取指定文件中的内容。
//向其传入文件路径、编码(可选参数)、以及会带上文件数据(以及错误)进行调用的回调函数:
const fs = require('fs')
fs.readFile('/Users/joe/test.txt', 'utf8' , (err, data) => {
if (err) {
// 读取成功err的值为null 读取失败err的值为错误对象,成功的数据为undefined
console.error(err)
return
}
console.log(data)
})
fs.writeFile()方法,用来向指定的文件中写入内容。
const fs = require('fs')
const content = '一些内容'
// 参数四个一个可选:一个文件路径的字符串,表示存放文件的路径;写入的内容;可选写入文件内容格式;文件写入完成后的回调函数。
fs.writeFile('/Users/joe/test.txt', content, err => {
if (err) {
console.error(err)
return
}
//文件写入成功。
})
fs.writeFile() 方法只能用来创建文件,不能用来创建路径
如果重复调用 fs.writeFile() 写入同一个文件,新写入的内容会覆盖之前的旧内容。
在使用fs模块之前需要先导入:require(导入的模块名)
const fs =require('fs')
文件路径中 __dirname表示当前文件所处的目录。
path模块是用来处理路径的模块,提供了一系列的方法和属性来满足对路径的处理需求。
如:path.join() 用来拼接一个完整的路径字符串。
使用前也需要先使用require导入。
../ 会抵消上一层的路径
路径拼接。
获取路径中的文件名:
path.basename() 方法。可以获取路径中的最后一部分。
path.basename(path[,ext])
// path文件路径
// ext表示文件扩展名,返回时会删除文件扩展名
// 返回路径的最后一部分
获取路径中的文件扩展名
path.extname(path) 传入一个路径的字符串,会返回一个扩展名字符串。
http模块
IP 地址
域名和域名服务器
创建 web 服务器的基本步骤
const http =require('http')
const server =http.createServer()
// 使用服务器实例的.on方法,为服务器绑定一个request事件
server.on('request',(req,res) => {
// 只要有客户端请求我们自己的服务器,就会触发request事件,从而调用这个事件处理函数
console.log('Someone visit our web server.')
})
req 请求对象:在事件处理函数中,访问与客户端相关的数据或属性,可以:
server.on('request',(req) => {
// req是请求对象,包含了与客户端相关的数据和属性,url是客户端请求路径,method是客户端的请求类型。
const str = `${req.url},${req.method}`
console.log(str)
})
server.on('request',(req,res) => {
// res是响应对象,包含了与服务器相关的数据和属性。
const str = `${req.url},${req.method}`
// res.end()方法的作用就是向客户端发送指定的内容,并结束这次请求的处理过程。
res.end(str)
})
④调用服务器实例的 .listen() 方法, 启动服务器,启动成功后就会调用第二个参数的方法。
// 调用server.listen(端口号,cb回调)方法,即可启动web服务器。
server.listen(80,()=>{
console.log('http server running at http://127.0.0.1')
})
使用res.end()方法向客户端发送内容时会出现乱码情况,我们需要手动设计内容的编码格式:
res.setHeader('Content-Type', 'text/html; charset=utf-8')
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
// 定义一个字符串,包含中文的内容
const str = `您请求的 URL 地址是 ${req.url},请求的 method 类型为 ${req.method}`
// 调用 res.setHeader() 方法,设置 Content-Type 响应头,值为:'text/html; charset=utf-8' ,来解决中文乱码的问题
res.setHeader('Content-Type', 'text/html; charset=utf-8')
// res.end() 将内容响应给客户端
res.end(str)
})
server.listen(80, () => {
console.log('server running at http://127.0.0.1')
})
动态响应内容
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
// 1. 获取请求的 url 地址
const url = req.url
// 2. 设置默认的响应内容为 404 Not found
let content = '<h1>404 Not found!</h1>'
// 3. 判断用户请求的是否为 / 或 /index.html 首页
// 4. 判断用户请求的是否为 /about.html 关于页面
if (url === '/' || url === '/index.html') {
content = '<h1>首页</h1>'
} else if (url === '/about.html') {
content = '<h1>关于页面</h1>'
}
// 5. 设置 Content-Type 响应头,防止中文乱码
res.setHeader('Content-Type', 'text/html; charset=utf-8')
// 6. 使用 res.end() 把内容响应给客户端
res.end(content)
})
server.listen(80, () => {
console.log('server running at http://127.0.0.1')
})
模块化
编程领域中的模块化,就是遵守固定的规则,把一个大文件拆成独立并互相依赖的多个小模块。 把代码进行模块化拆分的好处: 提高了代码的复用性 、提高了代码的可维护性 、可以实现按需加载。
模块化规范就是对代码进行模块化的拆分与组合时,需要遵守的那些规则。
模块化规范的好处:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用。
Node.js 中根据模块来源的不同,将模块分为了 3 大类,分别是:
- 内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)
- 自定义模块(用户创建的每个 .js 文件,都是自定义模块)
- 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
加载模块
使用 require() 方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。例如:
// 加载内置http模块
const http =require('http')
// 加载自定义模块
const custom = require('./custom.js')
自定义模块的加载机制:
使用 require() 加载自定义模块时,必须指定以 ./ 或 ../ 开头的路径标识符。在加载自定义模块时,如果没有指定 ./ 或 ../ 这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。 同时,在使用 require() 导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:
- 按照确切的文件名进行加载
- 补全 .js 扩展名进行加载
- 补全 .json 扩展名进行加载
- 补全 .node 扩展名进行加载
- 加载失败,终端报错
第三方模块的加载机制:
如果传递给 require() 的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘../’ 开头,则 Node.js 会从当前模块的父目录开始,尝试从 /node_modules 文件夹中加载第三方模块。
如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。
模块作用域
在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
模块作用域的好处:防止了全局变量污染的问题
向外共享模块作用域中的成员:module 对象/module.exports 对象
module 对象,它里面存储了和当前模块有关的信息
在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用。 外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象。
注意:使用 require() 方法导入模块时,导入的就是 module.exports 指向的对象。(默认情况下,exports 和 module.exports 指向同一个对象。但最终共享的结果,还是以 module.exports 指向的对象为准。)
建议使用时只使用其中一个对象导出,以免混淆。
CommonJS 模块化规范
CommonJS 规定了模块的特性和各模块之间如何相互依赖:
- 每个模块内部,module 变量代表当前模块。
- module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口。
- 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。
node入门文档 : Node.js 简介 (nodejs.cn)
在了解node基础、npm与包的概率以及模块化之后我们就可以开发一个属于自己的包了!