ES6:迭代器与生成器
迭代器我们经常使用 for 循环来遍历数组
let arr = ["red", "green", "blue"]for (let i = 0; i < arr.length; i++) { console.log(arr[i]);}
上述代码是使用变量 i 作为下标来访问数组,但是对于一些无序的集合,例如 Map 我们便不能通过下标的形式进行访问,所以有必要提供统一的方式来访问集合,这就是迭代器。
所谓的迭代器那当然是用来迭代用的,迭代的对象可以是数组,集合以及对象。迭代器含有一个方法 next(),该方法的作用就是从数组 (集合、对象) 取出一个值,它返回一个对象,对象中有两个属性:
done:为布尔值,false 表示集合中还有元素可遍历,true 表示集合中没有元素可遍历
value: 如果 done 为 false,value 的值为集合中的一个元素值,如果 done 为 true,value 的值为 undefined
function getIterator() { ...
Node.js之Buffer
Buffer 是 Node.js 的内置类型,它是用来表示内存中一块区域的,它保存的是二进制数据,可以将它看做为一个二进制数组。
Buffer 可以用来表示图片、视频这样的二进制数据,另外我们从文件中读取到的也是 Buffer 类型的数据,从网络中接收的数据也是 Buffer 类型的数据,所以学习 Buffer 还是很有必要的。
Buffer 位于全局作用域中,所以不需要通过 require('buffer') 来引入 Buffer。
创建 Buffer 对象alloc我们可以通过 Buffer.alloc(size, [fill], [encoding]) 来分配一个 size 字节大小的内存,还可以接收两个可选参数
fill:使用 fill 来填充 Buffer 中的每一个字节
encoding:如果 fill 为字符串,那么使用 encoding 来对字符串进行编码为二进制
当不指定 fill 参数,默认为填充 0。
const buf1 = Buffer.alloc(5);console.log(buf1); // <Buffer 00 00 00 0 ...
Node.js之MongoDB
本章讲解如何使用 Node.js 操作 MongoDB 数据库。分为两部分
MongoDB 的安装与使用
Node.js 第三方模块 mongoose 的使用
MongoDB 简介MongoDB 是一个 NoSQL 数据库,它的数据组织结构为
数据库
集合
文档
一个数据库 (database) 包含多个集合 (collections),一个集合包含多个文档 (document),在 MongoDB 中,文档是 JSON 格式的对象
{ "_id": ObjectId("6008027ec026735cc4aab553"), "username": "Alice", "todo": "学习"}
进入 MongoDB 官网 进行安装
然后一直下一步进行安装即可。安装好之后,运行
net start MongoDB
就可以启动 MongoDB 服务,然后在命令行输入
mongo
即可连接到 MongoDB 服务器,然后进入 Mo ...
Node.js之Express入门
Express 是基于 Node.js 的 Web 框架,通过 Express 可以快速的搭建一个 Web 应用。
基本使用安装 express
mkdir express-democd express-demonpm init -ynpm i express --save
使用 Express 写一个简单的 Web 应用
// index.jsconst express = require('express');const app = express();app.get("/", (req, res) => { res.send("Hello World!");});app.listen(3000);
在上面我们创建了一个简单的 Web 服务器,服务启动在 3000 端口,当我们以 get 方法访问 / 路径时,会返回 Hello World!。
node index.js
路由路由定义了服务器如何对客户端的请求作出相应,它由一个特定的 URI 以及一个 HTTP 方法确定,每一个路 ...
Node.js之事件循环
Node.js 是单线程的,但是它却可以应用在高并发场景,原因就是它的事件循环机制。所以本篇文章来介绍 Node.js 的事件循环机制。
同步与异步因为 Node.js 是单线程的,代码的执行不能使用同步机制,因为同步执行会阻塞代码,在单线程中阻塞代码意味着整个程序都被阻塞到了,从而无法处理其他任务。其他后端语言会使用多个线程去执行代码,即使一个线程被阻塞到了,其他的线程也不会有影响。
所以 Node.js 使用异步的方式去执行代码,为了更好的理解异步的概念,我打个比方,假设你请我做一件事情,同步的方式就是你会一直等我将事情做完,在我把事情做完之前,你不能干别的事情;异步的方式就是你请我做一件事情,在我做事情的时候你可以干别的事,等到我将事情做完的时候我会去通知你。
以读取文件为例,我们来看同步的写法
const fs = require("fs");// 程序会被阻塞在这里,知道文件读取完毕const data = fs.readFileSync("./hello.txt", "utf-8");console.log(dat ...
Node.js之核心模块
Node.js 的模块分为三种:
核心模块
第三方模块
本地模块
本篇重点介绍 Node.js 中的核心模块,包括
核心模块
作用
path
路径相关
fs
操作文件
os
提供相关操作系统信息
http
搭建 http 服务器
querystring
解析请求参数
pathpath 是我们介绍的第一个核心模块,所以有必要介绍如何引入核心模块。引入核心模块很简单,直接 require('xxx') 即可,例如我们引入 path 模块
const path = require("path");
path 是与路径有关的模块,再介绍 path 之前,介绍两个与路径有关的变量, __dirname 与 __filename:
__dirname:表示当前模块所在的目录,是一个表示绝对路径的字符串
__filename:表示当前模块(文件)所在的路径,也是一个表示绝对路径的字符串
这两个变量都是全局变量 global 的属性,所以可以直接在模块中访问
// D:\Desktop\Node\2 核心模块\1. path ...
ES6:Set集合与Map集合
在 ES6 以前,JavaScript 只有数组这一种集合来存储数据(当然有的人会使用对象来存储数据),在 ES6 中引入了两种新的集合来存储数据,它们是 Set 和 Map:
Set:Set 集合中的数据都不相同
Map:数据格式为键值对,与对象类似
ES5 中的 Set 和 Map模拟 Set 和 Map在 ES5 中,开发者使用对象来模拟 Set 和 Map
let set = Object.create(null);set.foo = trueif (set.foo) { // do something}
上面在 Set 集合中存储了一个名为 foo 的数据,通过将它的值设置为 true 来指明集合中有这个数据。
let map = Object.create(null);map.foo = "bar"console.log(map.foo); // bar
上述代码创建了一个 map 集合,并且在其中存储 foo-bar 这个键值对。
存在的问题问题是由于对象的特点引起的,在 JavaScript 中,对象的键值都是字符串 ...
Node.js 之模块系统
Node.js 提出的背景背景Node.js 于 2009 年由 Ryan Dahl 提出,它提出 Node.js 是为了解决当时的并发连接问题。以往的编程语言对于请求的处理方式是,来一个请求就新建一个线程来处理这个请求,假设一个线程需要消耗 2MB 的内存资源,那么对于一个 8GB 的内存系统,它最多同时处理 4000 个请求。如果需要处理更多的请求的话,就需要增加更多的服务器,另外由于用户的每个请求可能访问不同的服务器,所以所有的资源都需要在服务器之间共享。这种 Web 架构下瓶颈就在于服务器能够处理的并发连接的最大数量。
Node.js 提出另一种方法来解决这种问题,那就是事件绑定。每次来到一个请求,并不是为该请求新建一个线程,而是为该请求绑定一个事件,并且添加到事件队列,而最终达到的效果是,使用 Node.js 的服务器能够同时处理数万个并发连接。
如果将服务器比作是一个饭店,而一个请求就是一个客人。对于使用多线程的方式的服务器,来一个客人就派一个服务生去服务客人,直至客人离开。而 Node.js 则是只有一位服务员,这位服务员不会从头到尾都服务客人,每来一个客人,在了解完客人 ...
ES6:Symbol 和 Symbol 属性
在 ES6 中引入一种新的原始类型,那就是 Symbol 。Symbol 类型的值唯一的,每个被创建出来的 Symbol 变量都是不同的,这是 Symbol 这种数据类型最大的特点。
创建Symbol 不能通过字面量来进行创建,创建 Symbol 变量需要通过 Symbol() 来创建
let x = Symbol();console.log(typeof x); // symbol
let x = Symbol();let y = Symbol();console.log(x == y); // false
Symbol 类型的变量可以作为对象的属性,因为每一个 Symbol 变量是唯一的,所以不会出现属性被别人覆盖的问题,以及可以设置为私有属性,别人无法访问
let x = Symbol()let person={ [x]: 'Alice'}console.log(person[x]); // Alice
Symbol 还可以接收一个字符串作为该 Symbol 变量的描述,该字符串纯粹是为了调试方便而设置的,没有特殊的功能,两个 ...
匹配问题
最大匹配与完全匹配下面我们讲解的算法都是有关于二分图的算法
例如对于上图就是一个二分图,每条边都连接了两个不同部分的节点,生活中很多问题都可以建模为二分图的问题,例如相亲。左边表示男生群体,右边表示女生群体,如果两个节点之间有一条边,说明这一对男女可以匹配为一对;另外又比如求职,左边的节点表示求职者,右边的节点表示公司,如果节点之间有一条边,表明求职者与公司互相都比较满意,可以匹配。
现在我们关心的问题是,向这样的二分图最多有多少个匹配,这样的问题称为最大匹配问题,如果最大匹配的个数与左右两边的节点数目都相同,那么就称为是完全匹配,对于相亲来说,意味着每一个人都可以找到另一半,对于求职来说,每个求职者都可以找到一家公司。
最大流解决匹配问题解决最大匹配问题的一个方案就是将上面的图建模为一个网络流
图中的每一条边的权值都为 1,即每条边的允许通过的最大流量为 1,表示每一个节点都只能被匹配一次,此时这个网络流的最大流就等于最大匹配数,我们将求二分图的最大匹配问题转化为了求网络流的最大流问题,而求最大流的问题我们在以前已经接触过。
我们唯一需要的工作量就是根据上面的二分图得到一个网 ...