Node.js学习
语法
示例代码一
watcher.js
'use strict';
const fs = require('fs');
fs.watch('target.txt', () => console.log('File changed!'));
console.log('Now watching target.txt for changes...');
- 让代码在严格模式下运行,严格模式是ECMAScript 5 的新特性:
‘use strict’
- const 关键词,它声明fs 为常量,使用const 声明的常量必须在声明时赋值,而且禁止任何形式的再次赋值(会触发运行时报错)。
- require()函数用于引入Node.js 模块并且把这个模块作为返回值。执行require(‘fs’)是为了引入Node.js 内置的文件模块。
在Node.js 中,模块是一段独立的JavaScript 代码,它提供的功能可以用于其他地方。模块还可以依赖别的模块,类似于其他编程语言中库的概念,其他编程语言中的库也可以是import 或#include 其他库。
- 调用fs 模块的watch()方法,这个方法接收两个参数,一个是文件路径,另一个是当文件变化时需要执行的回调函数。
在JavaScript 中,函数是一等公民,也就是说,函数可以被赋值给变量,或者作为参数传递给别的参数。
5.回调函数:
() => console.log(‘File changed!’)
这是箭头函数表达式,也称胖箭头函数或简称为箭头函数。开头空括号的意思是这个函数不需要任何参数。函数体中使用console.log 把一段消息输出到标准输出。类似于冗长的写法:
function() {
console.log('File changed!');
}
示例代码二
watcher-argv.js
'use strict';
const fs = require('fs');
const filename = process.argv[2];
if (!filename) {
throw Error('A file to watch must be specified!');
}
fs.watch(filename, () => console.log(`File ${filename} changed!`));
console.log(`Now watching ${filename} for changes...`);
- 通过process.argv 访问命令行输入的参数。argv 是argument vector 的简写,它的值是数组,其中数组的前两项分别是node 和watcher‐argv.js 的绝对路径,数组的第三项(下标为2)就是目标文件的文件名target.txt。
- 注意输出信息是由反引号(```)包裹起来的字符串,称为模板字符串: ``File ${filename} changed!`
模板字符串支持多行文本,也支持插值表达式。利用插值表达式可以在${}占位符内写一个表达式,最终会用表达式的字符串值替换模板字符串中的占位符。
- let和const 都可以用于声明变量,但let声明的变量能够被多次赋值。通常我们会选const 关键词声明变量(常量),除非明确知道这个变量的值在运行时会修改,是块级作用域。
在引入const 和let 之前,在JavaScript 中都是用var 关键词声明变量的。var和let 类似,不同之处在于它声明的变量具有函数级作用域,而不是像let 一样的块级作用域。var创建变量后,变量提升,即var 语句声明的变量,会被提升到所在的函数或者模块作用域顶部。
Node.js 程序运行时,同步操作文件的两个阶段
初始化阶段
代码会做一些准备工作,导入依赖的库、读取配置参数等。如果在这个阶段发生了错误,我们没有太多办法,最好是尽早抛出错误并退出。因此在初始化阶段,可以考虑同步的文件操作。
代码执行阶段
事件循环机制开始工作。相当多的Node.js 应用是网络应用,也就是会建立连接、发送请求或者等待其他类型的I/O 事件。在这个阶段不要使用同步的文件操作,否则会阻塞其他的事件。
require()函数就是上述原则的最好例子,它同步地加载执行目标模块代码,返回整个模块对象。模块的加载要么成功,要么失败导致整个程序退出。
一般来说,如果文件操作失败会导致整个程序无法运行,就可以使用同步的方式。不管文件是否操作成功,程序都可以继续运行,最好使用异步的方式。
REPL
Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Window 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应。
Node 自带了交互式解释器,可以执行以下任务:
- 读取 - 读取用户输入,解析输入了Javascript 数据结构并存储在内存中。
- 执行 - 执行输入的数据结构
- 打印 - 输出结果
- 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
命令
- ctrl + c - 退出当前终端。
- ctrl + c 按下两次 - 退出 Node REPL。
- ctrl + d - 退出 Node REPL.
- 向上/向下 键 - 查看输入的历史命令
- tab 键 - 列出当前命令
- .help - 列出使用命令
- .break - 退出多行表达式
- .clear - 退出多行表达式
- .save filename - 保存当前的 Node REPL 会话到指定文件
- .load filename - 载入当前 Node REPL 会话的文件内容。
语法
- 下划线(_)获取上一个表达式的运算结果
- … 三个点的符号是系统自动生成的,你回车换行后即可。Node 会自动检测是否为连续的表达式。
NPM
- npm 安装 Node.js 模块:
npm 的包安装分为本地安装(local)、全局安装(global)两种,从敲的命令行来看,差别只是有没有-g而已
npm install < Module Name>
npm install express # 本地安装
npm install express -g # 全局安装
- npm卸载模块
npm uninstall express
- 更新模块
npm update express
- 搜索模块
npm search express
- 查看所有全局安装的模块(list或者ls)
npm list -g #查看全局所有
npm list -g express #查看全局express
npm list express #查看本地express
- package.json 位于模块的目录下,用于定义包的属性。
Node.js 回调函数
Node.js 异步编程的直接体现就是回调。
异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。
例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件 I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。
回调函数一般作为函数的最后一个参数出现:
function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }
Node.js 与JavaScript
Nodejs:
- ECMAScript(语言基础,如:语法、数据类型结构以及一些内置对象)
- os(操作系统)
- file(文件系统)
- net(网络系统)
- database(数据库)
JavaScript:
- ECMAScript(语言基础,如:语法、数据类型结构以及一些内置对象)
- DOM(一些操作页面元素的方法)
- BOM(一些操作浏览器的方法)
===:称为等同符,当两边值的类型相同时,直接比较值,若类型不相同,直接返回false;
==:称为等值符,当等号两边的类型相同时,直接比较值是否相等,若不相同,则先转化为类型相同的值,再进行比较;
JS闭包
子函数可以使用父函数的局部变量(包括参数,因为参数也是局部变量)
子函数用到了父函数的参数或者局部变量,一般都会形成闭包。
好处
1:具有封闭性,可以起到保护变量的作用
2 :避免全局变量的污染
坏处:导致内存泄露
解决方案:在内部匿名函数引用之前通过一个变量接受一下,然后用完之后置为空也可以解决内存泄露问题
var、let、const三者的区别
- ECMAScript是一个国际通过的标准化脚本语言。JavaScript由ECMAScript和DOM、BOM三者组成。可以简单理解为:ECMAScript是JavaScript的语言规范,JavaScript是ECMAScript的实现和扩展。
2011 年,ECMAScript 5.1 版发布。之前我们大部分人用的也就是ES5
2015 年 6 月,ECMAScript 6 正式通过,成为国际标准。
-
ES5 中作用域有:全局作用域、函数作用域。没有块作用域的概念。
-
ES6 中新增了块级作用域。块作用域由 { } 包括,if语句和 for语句里面的{ }也属于块作用域。
var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。 let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。 const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。