JavaScript运行时node.js基础
一、什么是node.js?
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时(C++语言编写),打破了过去JavaScript只能在浏览器中运行的局面。Node.js 应用程序在单个进程中运行,无需为每个请求创建新的线程。 Node.js 在其标准库中提供了一组异步的 I/O 原语,以防止 JavaScript 代码阻塞,通常,Node.js 中的库是使用非阻塞范式编写的,使得阻塞行为成为异常而不是常态。
浏览器和 Node.js 都使用 JavaScript 作为其编程语言,构建在浏览器中运行的应用程序与构建 Node.js 应用程序完全不同。在浏览器中,js大部分时间都是与 DOM 或其他 Web 平台 API(如 Cookies)进行交互,而在 Node.js 中没有浏览器提供的 document
、window
和所有其他对象,同样地浏览器中js没有类似访问数据库,文件系统的功能。
它的出现使得编写JavaScript 的前端开发者无需学习JAVA\C\C++\C#等后端语言,就可以编写除客户端代码之外的服务器端代码,因为nodejs提供了访问数据库、文件系统、网络读取等与服务端语言特性相关的支持。
Node.js有如下特点:
- 它是一个Javascript运行环境
- 依赖于Chrome V8引擎进行代码解释
- 异步事件驱动
- 非阻塞I/O
- 轻量、可伸缩,适于实时数据交互应用
- 单进程,单线程(这里指主线程)
- 高性能
- 大量的生态库
二、nodejs的安装
Node.js 可以通过多种方式安装,所有主流平台的官方软件包都可以在 http://nodejs.cn/download/ 获得。此处以在windows中安装为例,首先下载合适自己系统的安装包,如图:
使用该方式安装会自动将设置nodejs的环境变量(如果通过其他方式安装,可能需要设置环境变量),安装完成后打开 cmd命令行窗口 输入命令' node -v '查看版本,如果出现版本号,则表示安装成功,如图:
三、通过nodejs运行js脚本
在cmd命令行窗口或者编译器的cmd窗口中,使用' node *.js ' 命令可以在nodej环境中运行对应的js代码,需要注意的是如果在编译器中运行编写的完成项目,当服务启动后再次修改js代码后需要重启服务才能生效,我们可以使用 ' nodemon *js '命令来启动,该命令支持热更新。在控制台中运行程序时可以使用CTRL+C命令可以退出正在运行的Node.js程序,同时我们也可以使用编程的方式再触发某些事件后运行process.exit(0)来终止程序。
四、编写Node.js程序
为了快速的入门编写nodejs代码,应先熟悉如下代码示例,掌握常用的功能代码:
//process 核心模块提供了一种方便的方法,允许您以编程方式退出 Node.js 程序:process.exit()。 //默认的退出码为 0,表示成功。 不同的退出代码有不同的含义,可以在 http://nodejs.cn/api/process.html#process_exit_codes 阅读更多关于退出代码的信息。 process.exit(0) //Express 是一个在底层使用 http 模块的框架,app.listen() 返回一个 http 实例。 如果您需要使用 HTTPS 为您的应用程序提供服务,则使用 https.createServer,因为 app.listen 仅使用 http 模块。 const express = require('express') const app = express() //监听请求路径 app.get('/', (req, res) => { res.send('Hi!') }) //监听3000端口 app.listen(3000, () => console.log('Server ready')) //调用 process.exit(),则任何当前待处理或正在运行的请求都将被中止。 这并不好。我们可以通过传递信号SIGTERM ,并使用进程信号句柄处理它 process.on('SIGTERM', () => { server.close(() => { console.log('Process terminated') }) }) //从程序内部,在另一个函数中发送信号终止进程 process.kill(process.pid, 'SIGTERM')
//process 不需要 "require",它是自动可用的。 //Node.js 的 process 核心模块提供了 env 属性,该属性承载了在启动进程时设置的所有环境变量。 //在脚本运行之前将其设置为 "production",则可告诉 Node.js 这是生产环境。 process.env.NODE_ENV // "development"
//当使用以下命令调用 Node.js 应用程序时,可以传入任意数量的参数,参数可以是独立的,也可以具有键和值。 //获取参数值的方法是使用 Node.js 中内置的 process 对象。它公开了 argv 属性,该属性是一个包含所有命令行调用参数的数组。 node app.js name=joe node app.js joe //可以使用循环迭代所有的参数(包括 node 路径和文件路径) process.argv.forEach((val, index) => { console.log(`${index}: ${val}`) })
//Node.js 提供了 console 模块,该模块提供了大量非常有用的与命令行交互的方法。它基本上与浏览器中的 console 对象相同。 //最基础、最常用的方法是 console.log(),该方法会打印传入到控制台的字符串。如果传入对象,则它会呈现为字符串。可以传入多个变量到 console.log //可以通过传入变量和格式说明符来格式化用语:%s 会格式化变量为字符串,%d 会格式化变量为数字,%i 会格式化变量为其整数部分,%o 会格式化变量为对象 const x = 'x' const y = 'y' console.log(x, y)
//会清除控制台(其行为可能取决于所使用的控制台)。 console.clear() //在某些情况下,打印函数的调用堆栈踪迹 const function = () => console.trace() function() //可以使用 time() 和 timeEnd() 轻松地计算函数运行所需的时间 const doSomething = () => console.log('测试') const measureDoingSomething = () => { console.time('doSomething()') //做点事,并测量所需的时间。 doSomething() console.timeEnd('doSomething()') } measureDoingSomething()
//Progress 是一个很棒的软件包,可在控制台中创建进度条。 使用 npm install progress 进行安装。 const ProgressBar = require('progress') //以下代码段会创建一个 10 步的进度条,每 100 毫秒完成一步。 当进度条结束时,则清除定时器 const bar = new ProgressBar(':bar', { total: 10 }) const timer = setInterval(() => { bar.tick() if (bar.complete) { clearInterval(timer) } }, 100)
//从版本 7 开始,Node.js 提供了 readline 模块来执行以下操作:每次一行地从可读流(例如 process.stdin 流,在 Node.js 程序执行期间该流就是终端输入)获取输入。 const readline = require('readline').createInterface({ input: process.stdin, output: process.stdout }) //这段代码会询问用户名,当输入了文本并且用户按下回车键时,则会发送问候语。 //question() 方法会显示第一个参数(即问题),并等待用户的输入。 当按下回车键时,则它会调用回调函数。 readline.question(`你叫什么名字?`, name => { console.log(`你好 ${name}!`) readline.close() })
//Node.js 具有内置的模块系统。Node.js 文件可以导入其他 Node.js 文件公开的功能。当想要导入某些东西时,使用require导入,比如导入library.js公开的功能 const library = require('./library') //默认情况下,文件中定义的任何其他对象或变量都是私有的,不会公开给外界。可以通过exports把需要的功能公开给外部,外部就可以通过require引入并使用公开的功能 const car = { brand: 'Ford', model: 'Fiesta' } //公开car对象 exports.car = car
五、npm 包管理器
npm
是 Node.js 标准的软件包管理器。在 2017 年 1 月,npm 仓库中就已有超过 350000 个软件包,这使其成为世界上最大的单一语言代码仓库,并且可以确定几乎有可用于一切的软件包。它起初是作为下载和管理 Node.js 包依赖的方式,但其现在也已成为前端 JavaScript 中使用的工具。npm具有如下功能:
npm
可以管理项目依赖的下载:如果项目具有package.json
文件,则通过运行npm install,它会在node_modules
文件夹(如果尚不存在则会创建)中安装项目所需的所有东西(这些东西就配置在package.json中)。- 安装单个软件包:可以通过运行以下命令 npm install <package-name> 安装特定的软件包,其中命令可以携带参数 " --save " 表示安装并添加条目到 package.json 文件的 dependencies,参数"--save-dev"安装并添加条目到 package.json 文件的 devDependencies。
- 更新软件包:通过运行npm update或者npm update <package-name> 命令来更新所有包或指定包。
- 版本控制:除了简单的下载外,
npm
还可以管理版本控制,因此可以指定软件包的任何特定版本,或者要求版本高于或低于所需版本。指定库的显式版本还有助于使每个人都使用相同的软件包版本,以便整个团队运行相同的版本,直至package.json
文件被更新。 - 运行任务:通过命令 npm run <task-name> 运行指定任务,task-name在package.json 文件中的scripts节点下定义。比如如下定义中,运行npm run start 相当于运行node lib/server-production命令:
{ "scripts": { "start-dev": "node lib/server-development", "start": "node lib/server-production", "watch": "webpack --watch --progress --colors --config webpack.conf.js", "dev": "webpack --progress --colors --config webpack.conf.js", "prod": "NODE_ENV=production webpack -p --config webpack.conf.js", }, }
六、npm包管理器常见问题
- npm 将软件包安装到哪里:分为全局安装npm install -g xx和本地安装npm install xx两种方式,本地安装会安装到node_modules文件夹下,全局安装会安装到 npm root -g 输出的文件夹下。
- 如何使用或执行 npm 安装的软件包:安装完成软件包后,只需使用 const xx=require('name') 导入到使用的地方即可直接使用。
- package.json文件说:
package.json
文件是项目的清单。 它可以做很多完全互不相关的事情。 例如,它是工具的配置中心,它也是npm
和yarn
存储所有已安装软件包的名称和版本的地方,例如vue项目中配置:
{ "name": "test-project", "version": "1.0.0", "description": "A Vue.js project", "main": "src/main.js", "private": true, "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "unit": "jest --config test/unit/jest.conf.js --coverage", "test": "npm run unit", "lint": "eslint --ext .js,.vue src test/unit", "build": "node build/build.js" }, "dependencies": { "vue": "^2.5.2" }, "devDependencies": { "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", "babel-eslint": "^8.2.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-jest": "^21.0.2", "babel-loader": "^7.1.1", "babel-plugin-dynamic-import-node": "^1.2.0", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", "copy-webpack-plugin": "^4.0.1", "css-loader": "^0.28.0", "eslint": "^4.15.0", "eslint-config-airbnb-base": "^11.3.0", "eslint-friendly-formatter": "^3.0.0", "eslint-import-resolver-webpack": "^0.8.3", "eslint-loader": "^1.7.1", "eslint-plugin-import": "^2.7.0", "eslint-plugin-vue": "^4.0.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^1.1.4", "friendly-errors-webpack-plugin": "^1.6.1", "html-webpack-plugin": "^2.30.1", "jest": "^22.0.4", "jest-serializer-vue": "^0.3.0", "node-notifier": "^5.1.2", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", "portfinder": "^1.0.13", "postcss-import": "^11.0.0", "postcss-loader": "^2.0.8", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", "vue-jest": "^1.0.2", "vue-loader": "^13.3.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": ["> 1%", "last 2 versions", "not ie <= 8"] }
以上所有的这些属性都可被 npm
或其他工具使用,解释如下:
version
表明了当前的版本。name
设置了应用程序/软件包的名称。description
是应用程序/软件包的简短描述。main
设置了应用程序的入口点。private
如果设置为true
,则可以防止应用程序/软件包被意外地发布到npm
。scripts
定义了一组可以运行的 node 脚本。dependencies
设置了作为依赖安装的npm
软件包的列表。devDependencies
设置了作为开发依赖安装的npm
软件包的列表。engines
设置了此软件包/应用程序在哪个版本的 Node.js 上运行。browserslist
用于告知要支持哪些浏览器(及其版本)。
- package-lock.json作用:该文件用于锁定被安装的每个软件包的确切版本,以便产品可以以相同的方式被 100% 复制(即使软件包的维护者更新了软件包)。
- 查看 npm 包安装的版本:运行 npm list 或者npm list -g或者 npm list packname。
- 安装 npm 包的旧版本:先使用npm view <package> versions查看版本,再使用npm install packname@version 方式安装指定版本。
- 使用 npm 的语义版本控制:npm包都约定版本的语义,所有版本都有3个数字,为x.y.x格式,其中第一个数字是主版本,第二个数字是次版本,第三个数字是补丁版本。当发布新的版本时,不仅仅是随心所欲地增加数字,还要遵循以下规则:
- 当进行不兼容的 API 更改时,则升级主版本。
- 当以向后兼容的方式添加功能时,则升级次版本。
- 当进行向后兼容的缺陷修复时,则升级补丁版本。
该约定在所有编程语言中均被采用,每个 npm
软件包都必须遵守该约定,这一点非常重要,因为整个系统都依赖于此。
- 卸载 npm 软件包:运行 npm uninstall <package-name>命令或者npm uninstall
--save
-g <package-name>等带参数的命令。 - npm 依赖与开发依赖:开发依赖是仅用于开发的程序包(在devDependencies节点下),在生产环境中并不需要。 例如测试的软件包、webpack 或 Babel。当install命令添加了
-D
或--save-dev
参数时,则会将其安装为开发依赖项。
七、Nodejs常用模块使用
nodejs内置了文件系统、路径、操作系统、事件、http、Buffer、流等常用模块,使用方式代码举例如下:
八、Nodejs 文件属性
每个文件都带有一组详细信息,可以使用 Node.js 进行检查。具体地说,使用 fs
模块提供的 stat()
方法。调用时传入文件的路径,一旦 Node.js 获得文件的详细信息,则会调用传入的回调函数,并带上两个参数(错误消息和文件属性)。文件的信息包含在属性变量中。 可以通过属性:
- 使用
stats.isFile()
和stats.isDirectory()
判断文件是否目录或文件。 - 使用
stats.isSymbolicLink()
判断文件是否符号链接。 - 使用
stats.size
获取文件的大小(以字节为单位)。
const fs = require('fs') fs.stat('/Users/joe/test.txt', (err, stats) => { if (err) { console.error(err) return } stats.isFile() //true stats.isDirectory() //false stats.isSymbolicLink() //false stats.size //1024000 //= 1MB })
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通