mongoDb练习一

练习1

  1. 进入my_test数据库
1
use my_test
  1. 向 my_test中 user集合插入一个文档

集合习惯会在其后加s 所以 user在操作时是 db.users

1
db.users.insert({username:"猪八戒"})
  1. 查询user集合中的文档
1
db.users.find()
  1. 向user集合中插入一个文档
1
db.users.insert({username:"孙悟空"})
  1. 统计user集合中文档document的数量
1
db.users.find().count()
  1. 查询user集合中 username为孙悟空的值
1
db.users.find({username:"孙悟空"})
  1. 向user集合中 username=”孙悟空”的文档添加一个 address= 花果山
1
2
3
4
5
6
7
db.users.update({username:"孙悟空"},{
{
$set:{
{address:"花果山"}
}
}
})
  1. 使用{username:”唐僧”}替换 username为 猪八戒 的文档
1
db.users.replaceOne({username:"猪八戒"},{username:"唐僧"})
  1. 删除 username 为 孙悟空 的 address属性
1
db.users.update({username:"孙悟空"},{$unset:{address:""}})
  1. 向 username 为 孙悟空 的文档中 添加一个 hobby:{cities:[“北京”,”上海”,”深圳”],movies:[“三国”,”英雄”]}
1
2
3
4
5
6
7
8
db.users.update({username:"孙悟空"},{
$set:{
hobby:{
cities:["北京","上海","深圳"],
movies:["三国","英雄"]
}
}
})

mongodb 中的属性值也可以是一个文档,当一个文档的一个属性值是文档时,我们称之为「内嵌文档」

  1. 向 username 为 唐僧 的文档中 添加一个 hobby:{movies:[“大话西游”,”天下第一”]}
1
2
3
4
5
6
7
db.users.update({username:"孙悟空"},{
$set:{
hobby:{
movies:["大话西游","天下第一"]
}
}
})
  1. 查询喜欢 电影 movies = 英雄 的文档
  • mongodb支持直接通过内嵌文档的属性进行查询,使用「.」进行操作 形如 hobby.movies的形式
  • 通过内嵌文档查询 必须使用引号包起来 形如 “hobby.movies”
1
db.users.find({"hobby.movies":"英雄"})
  1. 向 唐僧 的文档中,电影 movies 中添加 “寒战”
  • 注意此时不要用 $set 修改操作符
  • 使用 $push 用于向数组中添加一个新的元素(可重复添加)
  • $addToSet 向数组中添加一个元素 (如果添加元素已经存在就不会再去添加了,不可重复添加)
1
2
3
4
5
6
7
8
9
10
11
db.users.update({username:"唐僧"},{
$push:{
"hobby.movies":"寒战"
}
})

db.users.update({username:"唐僧"},{
$addToSet:{
"hobby.movies":"寒战"
}
})
  1. 删除 喜欢 北京 的用户
1
db.users.remove({"hobby.cities":"北京"})
  1. 删除 users集合
1
2
db.users.remove({}) 
db.users.drop()

mongoDb入门一

mongodb入门

windows用户推荐下载3.4 (3.6会卡在一个进度不动)

官网

解压后一路next 然后在对应目录建立目录

1
2
3
data/db
# 命令行中输入如下即可启动 mongodb
mongod --dbpath "f:/mongodb/data"

执行mongo命令

1
2
3
4
5
6
7
8
9
# 进入mongo命令行环境  path请自行添加
mongo
```

> 如果安装不了 你可以使用官方提供的在线版(mongodb官网 doc中 /MongoDB CRUD Opeartions/Insert Document)



### 常用命令

show dbs 查看所有库
use test 使用test数据库 如果test不存在则创建
db.p 操作collections p就是mysql表的概念 有就使用没有则创建

1
2
3
4
5
6

### CRUD

#### 增

> 增加的时候会默认生成 _id 确认数据的唯一标识

use test
db.p.insert({name:”aa”})
db.p.insert({name:”aa”},{name:”bb”})
db.p.insertOne({name:”aa”})
db.p.insertMany({name:”aa”},{name:”bb”})

#如果你想不要生成的 _id 就可以传递该自动进行覆盖
db.p.insertOne({_id:”hello”,name:”aa”})

1
2

#### 查

查所有

db.p.find() / db.p.find({})

按字段查

db.p.find({name:”aa”})

多个字段 name为aa age为 18

db.p.find({name:”aa”,age:18})

find返回的是数组

findOne() 返回匹配的第一个文档

db.p.findOne({age:18}).name

find返回的个数

db.p.find().count()

1
2

#### 修改

假如数据为{_id:Object(“3124912ui9012i8fsdafdsf”) ,name:”唐僧”,age:40,gender:”man”}
db.p.update({name:”唐僧”},{age:999})
数据更新为 {_id:Object(“3124912ui9012i8fsdafdsf”),age:999}
update默认 会覆盖

1
2

修改操作符避免覆盖 $set

db.p.update({_id:Object(“3124912ui9012i8fsdafdsf”)},
{
$set:{
name:”沙和尚”
}
}
)

1
2

删除文档的指定属性$unset

db.p.update({_id:Object(“3124912ui9012i8fsdafdsf”)},
{
$unset:{
gender:”这个值写不写没关系因为是删除的”
}
}
)

1
2

update默认只会改第一个匹配的数据

db.p.updateOne({name:”八戒”},
{
$set:{
address:”天宫”
}
}
)

db.p.updateMany({name:”八戒”},
{
$set:{
address:”天宫”
}
}
)

我就要用 update更新多条数据

db.p.update({name:”八戒”},
{
$set:{
address:”天宫”
}
},
{
multi:true //修改多条
}
)

#替换一个文档
db.p.replaceOne({name:”八戒”}, { address:”天宫” })

1
2

#### 删除

db.p.remove() 不传递参数报错
db.p.remove({}) 全删了,性能比较查 一个一个删
db.p.remove({name:”aa”}) //默认删除多个
db.p.remove({name:”aa”},true) //删除一个
db.p.deleteOne({name:”aa”})
db.p.deleteMany({name:”aa”})

1
2

删除相关操作

db.p.remove({}) 全删了,集合还在,性能比较差 一个一个删
db.p.drop() 清空集合,性能好 集合没了
db.dropDatabase() 删库
`

node ten Modules(初始)

给迷茫的你学习Node.js最好的方法

原文连接

每天10个 npm 模块

仓库地址

Array

is-sorted

A small module to check if an Array is sorted.

核心代码 index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
function defaultComparator (a, b) {
return a - b
}

module.exports = function checksort (array, comparator) {
comparator = comparator || defaultComparator

for (var i = 1, length = array.length; i < length; ++i) {
if (comparator(array[i - 1], array[i]) > 0) return false
}

return true
}

test.js

1
2
3
4
5
6
7
8
9
10
var sorted = require('./index')

console.log(sorted([1, 2, 3]))
// => true

console.log(sorted([3, 1, 2]))
// => false

// supports custom comparators
console.log(sorted([3, 2, 1], function (a, b) { return b - a }))

express三连(一)

Router用法

simpleRouter.js

1
2
3
4
5
6
7
8
9
10
11
const router = require('express').Router();

router.get('/',(req,res)=>{
res.json({code:0,msg:'welcome to simple root router'})
})

router.get('/simple_demo',(req,res,next)=>{
res.end(`your simple_demo here`)
})

module.exports = router;

anotherRouter.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const router = require('express').Router();


router.route('/')
.get((req,res)=>{
res.json({code:0,msg:'welcome to another root router get method'})
})
.post((req,res)=>{
res.json({code:0,msg:'welcome to another root router post method'})
})


router.get('/another_demo',(req,res,next)=>{
res.end(`your another_demo here`)
})

module.exports = router;

server001.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var express = require('express');
var app = express();
const bodyParser = require('body-parser');

const simpleRouter = require('./simpleRouter')
const anotherRouter = require('./anotherRouter')

app.use(bodyParser.urlencoded({extended:false}))

app.use('/simple/',simpleRouter);
app.use('/another/',anotherRouter);

app.use((err,req,res,next)=>{
res.status(401)
res.json({code:-1,msg:err.message})
})

app.listen(8001,()=>{
console.log('port 8001 is listening!')
});

使用express生成器(类似vue-cli脚手架的工具)

安装express模板生成器

1
npm install express-generator -g

创建目录(你的项目目录)

1
mkdir one_punch

生成模板

1
2
# --view==ejs 代表设置支持ejs语法的模板文件
express --view=ejs one_punch

切换项目目录,安装依赖

1
2
cd one_punch
npm install

启动项目

1
npm start

默认监听3000端口

打开浏览器你会看到生成的express页面

  • localhost:3000
  • localhost:3000/users

express三连(一)

express

基于 Node.js 平台,快速、开放、极简的 web 开发框架。

express

express helloworld

  1. 初始化项目(请确保你安装了node)
1
2
3
4
5
6
mkdir demo
cd demo
# 初始化 package.json 一路回车
npm init
# 安装express 我的是4.16.3版本
npm install express --save
  1. 创建server.js
1
2
3
4
5
6
7
8
9
10
var express = require('express');
var app = express();

app.get('/', function(req, res){
res.send('hello world');
});

app.listen(8001,()=>{
console.log('port 8001 is listening!')
});
  1. 开启服务器 node server.js

  2. 浏览器访问 localhost:8001

参数信息

请求url为 http://localhost:8001/?name=22

1
2
3
4
5
6
7
8
9
10
app.get('/', function(req, res){
//获取请求方式
console.log(req.method)
//请求参数为 k/v形式
console.log(JSON.stringify(req.query));
//根据url取参数
console.log(req.query.name);
//返回数据
return res.json({code:0})
});

restful风格的匹配参数

restful风格 http://localhost:8001/aa/18/man

1
2
3
4
5
6
app.get('/:name/:age/:gender', function(req, res){
console.log(req.params.name);
console.log(req.params.age);
console.log(req.params.gender);
return res.json({code:0})
});

获取请求头和设置响应头

  • request.get()
  • response.set()
1
2
3
4
5
6
// 获取请求头 和设置响应头
app.get('/', function(req, res){
console.log(req.get('Accept'));
res.set('token','fdsalkjljjfadslkjfds')
return res.json({code:0})
});

设置json格式的响应类型

  • res.json({code:0})
  • 麻烦的方式 先设置Content-Type 在去调对象序列化字符串
1
2
3
4
// 响应json格式
app.get('/', function(req, res){
return res.json({code:0})
});
1
2
3
4
5
// 响应json格式
app.get('/', function(req, res){
res.set('Content-Type','application/json;charset=utf-8')
return res.send(JSON.stringify({code:0}))
});

设置状态码

1
res.status(404)

get && post

1
2
3
4
5
6
7
app.get('/', function(req, res){
return res.json({code:0})
});

app.post('/', function(req, res){
return res.json({code:0})
});

app.use()

可以直接包含 get、post 等的匹配就不用同一路径分开写了 app.get(‘/user’,[args…]) app.post(‘/user’,[args..])

1
2
3
4
5
6
7
8
9
var express = require('express');

app.use('/',(req,res,next)=>{
res.json({msg:"use"})
})

app.listen(8001,()=>{
console.log('port 8001 is listening!')
});

中间件

类似promise里的 .then().then().then() 的加工处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var express = require('express');
var app = express();

// const Router = express.Router();

app.use('/',mod1,mod2)

function mod1(req,res,next){
console.log('进入 mod1 厂房')
return next();
}

function mod2(req,res,next){
console.log('进入 mod2 厂房')
res.json({msg:'数据返回结束'})
}

app.listen(8001,()=>{
console.log('port 8001 is listening!')
});

use使用中间件的方式

1
2
3
app.use('/',mod1,mod2)
app.use('/',[mod1,mod2])
app.use('/',[mod1],mod2)

处理过程中通过req携带参数

1
2
3
4
5
6
7
8
9
10
11
12
13
app.use('/',mod1,mod2)

function mod1(req,res,next){
console.log('进入 mod1 厂房')
req.user = {name:"fsafsdfas"};
return next();
}

function mod2(req,res,next){
console.log('进入 mod2 厂房')
console.log(JSON.stringify(req.user))
res.json({msg:'数据返回结束'})
}

next() 控制流程

  • 不传递参数就会进入下一个中间件
  • 传递Error对象 就会走进错误的处理分支
  • 传递字符串 也会进入错误的处理分支 但是获取不到错误信息
  • 传递字符串除非你是’route’ 否则都会进入错误分支
1
2
3
4
next()
next(new Error('fdsfdsa'))
next('fdsafsa')
next('route')

中间件的兜底处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var express = require('express');
var app = express();

app.use('/',mod1,mod2)

function mod1(req,res,next){
console.log('进入 mod1 厂房')
return next(new Error('少了一个零件,请求召回'));
}

function mod2(req,res,next){
console.log('进入 mod2 厂房')
res.json({msg:'数据返回结束'})
}

//兜底处理
app.use((err,req,res,next)=>{
res.status(401)
res.json({code:-1,msg:err.message})
})

app.listen(8001,()=>{
console.log('port 8001 is listening!')
});

处理请求体 body-parser

安装 body-parser

1
npm install body-parser --save
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var express = require('express');
var app = express();

const bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({extended:false}))

app.use('/',mod1,mod2)

function mod1(req,res,next){
//打印解析后的请求体
console.log(req.body)
console.log('进入 mod1 厂房')
return next()
// return next(new Error('少了一个零件,请求召回'));
}

function mod2(req,res,next){
console.log('进入 mod2 厂房')
res.json({msg:'数据返回结束'})
}

app.use((err,req,res,next)=>{
res.status(401)
res.json({code:-1,msg:err.message})
})

app.listen(8001,()=>{
console.log('port 8001 is listening!')
});

小型node服务器

node增删改查

localhost:8200/user 获取所有用户(GET)

localhost:8200/user 创建一个用户(POST)

localhost:8200/user/aaa 修改一个用户(PATHC)

localhost:8200/user/bbb 删除一个用户(DELETE)

Content-Type:application/json

1
{"name":"aaa","age":118}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const http = require('http');
const server = http.createServer();
const url = require('url')

let users = [
{name:"aaa",age:18},
{name:"bbb",age:34},
{name:"ccc",age:22},
{name:"ddd",age:13},
{name:"eee",age:19},
{name:"fff",age:28}
];
server.on('request',(req,res)=>{
console.log('请求方式==>'+req.method)
console.log('请求的路径==>'+req.url)

//获取请求的路径
const parseUrl = url.parse(req.url)

if(parseUrl.path.indexOf('/user')===-1){
res.statusCode = 403;
res.end(`${res.statusCode} not allowed!`)
return;
}
console.log(req.method)
switch(req.method){
case 'GET':
console.log('get users')
res.statusCode = 200;
res.end(JSON.stringify(users))
break;
case 'POST':
console.log('create user')
let user = '';
req.on('data',(buffer)=>{
const userStr = buffer.toString();
let CT = req.headers['content-type'];
if(CT === 'application/json'){
user = JSON.parse(userStr);
users.push(user);
}
})
req.on('end',()=>{
res.statusCode = 201;
res.end('user has created!')
})
break;
case 'PATCH':
console.log('update users')
// /user/aaa
let userName = parseUrl.path.substring(6)
console.log(userName)
req.on('data',(buffer)=>{
const userStr = buffer.toString();
let CT = req.headers['content-type'];
if(CT === 'application/json'){
let update = JSON.parse(userStr)
let user = users.find(u=>u.name === userName)
user.age = update.age;
}
})
req.on('end',()=>{
res.statusCode = 201;
res.end('user has updated!')
})
break;
case 'DELETE':
console.log('DELETE user')
if(parseUrl.path.indexOf('/user/')>-1){
let userName = parseUrl.path.substring(6)
let index = users.findIndex(u=>u.name === userName);
users.splice(index,1);
res.statusCode = 200;
res.end(JSON.stringify(users))
}
break;
}
})

server.listen(8200)

node从零开始之HTTP

HTTP(HyperText Transfer Protocol) 超文本传输协议

维基百科中文

HTTP格式

文本

HTTP的组成部分

详情请看我写的 HTTP入门文章

  1. 动词 路径 协议/版本 第一部分路径随便写 一定要以”/“开头
  2. 第二部分 键值对
    • Key1: value1
    • Key2: value2
    • Key3: value3
    • Content-Type: application/x-www-form-urlencoded
    • Host: www.baidu.com
    • User-Agent: curl/7.54.0
  3. 回车 就一个目的区分 第二部分和第四部分
  4. 要上传的数据

推荐使用的测试工具 postman

方便调试http请求的工具

download

postman

  • get 获取数据
  • post 新增数据
  • patch 更新资源
  • delete 删除数据
  • head 不用实际请求资源的时候,获取文件的相关信息(大小/长度/权限)

    对一个资源发一个head请求就会返回它的头文件(里面包含CDN 上的资源/图片/视频的相关信息)

  • options 向服务器询问我能通过那些方法去操作这个资源(区分管理员/游客信息)

具体风格请去看 restful 相关的约定

响应头

维基百科HTTP状态码

  • 200 OK 响应成功啦
  • 201 Created 创建资源的时候做一个返回
  • 202 服务器已接受但是没有处理(最终请求可能会也可能不会被执行)
  • 206 断点续传。下载时(文件比较大100MB)先返回10M 你下载好后下次再从10M的节点去要后面的10M
  • 302 Found 重定向(资源被放到了其他地方)
  • 304 Not modified 表示资源未修改返回上一次请求的内容(但是仍然触发了请求)
  • 400 参数不对 返回请求失败的一些原因
  • 401 服务器向客户端询问权限的一个响应头
  • 403 服务器已经收到,但是拒绝执行。 通常告诉用户权限不够
  • 404 未找到页面
  • 500
  • 502 网关错误
  • 504 超时

推荐书籍

  • 图解HTTP(简单)推荐这本
  • HTTP权威指南(工具书)

node 模块化

最简单的模块点定义

module_a.js

1
2
3
function haha(){console.log(1)}

exports.haha = haha;

main.js 使用module_a.js

1
2
var mod = require('./module_a')
mod.haha()
  • 系统模块用绝对路径如 requier(‘http’)
  • 自有模块要用相对路径 requier(‘./module_a’)

同一模块导出多个变量或方法

module_a.js

1
2
3
function haha(){console.log(1)}

function lala(){console.log(2)}

每个都指定一下

1
2
module.exports.haha = haha;
module.exports.lala = lala;

多个导出

1
2
3
4
module.exports = {
haha,
lala
}

node 之字里行间创建一个服务器

node可以很简短的几句话就可以创建一个服务器

1
2
3
4
5
6
7
8
const http = require('http');
let server = http.createServer();

server.on('request',(request,response)=>{

})

server.listen(8200)

继承

编程语言的佛魔道

流派

面向对象

  • 总所周知的Java 一切皆对象(一不自觉我就想到think in java里的特别形象的灯泡图,真的是秒懂什么是方法什么是类)
  • 什么是类(同一事物的抽象描述)
  • 对象(实例)
  • 封装
  • 继承
  • 多态
  • 反射

函数式

  • JavaScript
  • 算子
  • lamda
  • 柯里化
  • 高阶函数
  • 纯函数

所以这就好比佛教和道教,每个流派都有自己的信仰。所以说编程语言上升到宗教层面还是挺可怕的

如果说上面不好理解,可以说说军队,武警和解放军虽然都是国防力量,但是性质不一样,一个对内(处突维稳,抢险救灾)一个对外(抵抗外敌)

所以说不能拿java特有的东西去看待js

JS之假继承

ES6新特性class出来之前 JS是没有继承的(都是模拟的)

JS有原型「prototype」共有属性

1
2
3
4
5
6
var a = new Object()
// a可以调用toString()
a.toString()

//我们知道 a.__proto__ = Object.prototype
Object.prototype 上有toString()

1
2
3
4
5
6
7
8
9
// Object是所有对象的基类

var a = new Array()
a.valueOf() //a自己没有valueOf()

//Array的原型没有valueOf()
Array.__proto__ = Array.prototype
//Object的原型有valueOf() 二次的原型查找
Array.__proto__.__proto__ = Object.prototype

JS是没有类的概念的,只有原型

但是面试官认为是有的。。。(因为人都会拿相似的东西去推测没接深入触过的东西)

什么是类

能产生对象的东西就是「类」

  1. 非常纯粹的人类对象
1
2
3
function Human(){}
var person = new Human()
// person就是一个对象了
  1. 人类应该有个名字
1
2
3
4
5
function Human(name){
this.name = name
}
var person = new Human('aa')
person.name // aa
  1. 人类应该有些技能比如 跑
1
2
3
4
5
6
7
8
9
function Human(name){
this.name = name
}
Human.prototype.run = function(){
console.log('run')
}
var person = new Human('aa')
person.name // aa
person.run() // run
  1. 人类还有子类 比如 男人
1
2
3
4
5
6
7
8
// 男人类 他有一个属性就是性别
function Man(name){
this.gender = '男'
}
// 男人天生会打架
Man.prototype.fight = function(){
console.log('糊你熊脸')
}
  1. 我们希望 Man 应该有个名字
1
2
3
4
5
6
7
8
9
10
11
12
13
//人类
function Human(name){
this.name = name
}
// 男人类 他有一个属性就是性别
function Man(name){
Human.call(this,name)
this.gender = '男'
}
// 男人天生会打架
Man.prototype.fight = function(){
console.log('糊你熊脸')
}
  1. 我们希望 Man 会跑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//人类
function Human(name){
this.name = name
}
Human.prototype.run = function(){
console.log('run')
}
// 男人类 他有一个属性就是性别
function Man(name){
Human.call(this,name)
this.gender = '男'
}
// 男人天生会打架
Man.prototype.fight = function(){
console.log('糊你熊脸')
}
Man.prototype.__proto__ = Human.prototype;

//然后你声明一个 m1
var m1 = new Man('m1')
m1.__proto__ = Man.prototype
m1.__proto__.__proto__ = Human.prototype
m1.__proto__.__proto__.__proto__ = Object.prototype

以上就是一个ES5完整的继承

核心只有两句话

1
2
Human.call(this,name)
Man.prototype.__proto__ = Human.prototype;

但是IE里不允许你操作「下划线proto下划线」

我们可以像这样来模拟继承

1
Man.prototype = new Human()

虽然 new Human()产生的对象的

但是这样 new Human( )会产生一个对象 假设为temp

temp会自带一个name属性 这个是我们不想要的

我们只想要Human的原型上的东西

于是我们用这三句代替

1
2
3
4
5
6
7
8
//step1声明一个空函数,里面什么属性也没有
var f = function(){}

//step2 让空函数「f」原型 = Human.prototype
f.prototype = Human.prototype

//step3 生成一个「f」对象因为它是个空函数
Man.prototype = new f()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Human(name){
this.name = name
}
Human.prototype.run = function(){
console.log("我叫"+this.name+",我在跑")
return undefined
}
function Man(name){
Human.call(this, name)
this.gender = '男'
}

var f = function(){}
f.prototype = Human.prototype
Man.prototype = new f()

Man.prototype.fight = function(){
console.log('糊你熊脸')
}

ES6诞生了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Human{
constructor(name){
this.name = name
}
run(){
console.log("我叫"+this.name+",我在跑")
return undefined
}
}
class Man extends Human{
constructor(name){
super(name)
this.gender = '男'
}
fight(){
console.log('糊你熊脸')
}
}

extends就是为了连接原型链

1
2
Man extends Human 就是为了实现
Man.prototype.__proto__ = Human.prototype
1
super(name) 就是Human.call(this,name)

题外话

ES5方式的继承印证了,我对JS内存的理解

ES6方式你可以自行去浏览器里打印,你会发现它还是用的prototype实现继承的

也就是说ES6的继承会翻译成ES5的写法,如果你是Js程序员应该用ES5的写法,ES6是方便java程序员的写法。

如果你想给 Human 的原型添加一个种族是 人类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ES5
Human.prototype.s = '人类'


// ES6 对不起,不支持,有一种变通的写法

class Human{
constructor(name){
this.name = name
}
//麻烦不????
//麻烦不????
//麻烦不????
get s(){
return '人类'
}

run(){
console.log("我叫"+this.name+",我在跑")
return undefined
}
}

ES5写法证明你是JS程序员

ES6写法证明你是Java程序员

axios设置token

axios之后台死活接不到的token参数

https://zhuanlan.zhihu.com/p/27594936

近期在给公司做硬件后台于是就搭了一个vue-cli项目

  • 从单vue文件路由
  • 从路由到路由守卫(跳转前鉴权)
  • 从路由守卫到菜单鉴权
  • 引入iview组件到封装基于 iview(表格、分页、加筛选、前端排序)
  • 使用mixin混入对象
  • 其中也踩了很多坑

今天就说一个就是axios设置 headers

这个问题问了好多人好多群、大致的结果就是你设置就行了 然后后台直接取

问题1 登录发了两次请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import axios from 'axios'
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
Vue.prototype.$http= axios;

//在你登录的时候后台返回登录信息设置全局token请求头
let params = new URLSearchParams();

params.append('userAcnt',this.formSignIn.user);
params.append('nowPwd', this.formSignIn.password);
params.append('signInAvoid',0);
this.$http.post(ApiLink.URL_LOGIN,params).then((res)=>{
//登录逻辑
//获取token 从res里获取 我就不多说了
this.$http.defaults.headers.token = token;
})

如图

step

step

step

  1. 简单来说就是后台以为 「OPTIONS」就是你实际的请求了
  2. 然后想方设法的去取 「Access-Control-Request-Headers: token 」里的内容,断点的去看请求发现 token 一直是字符串的 ‘token’ (键名)
  3. 实际上第二次的请求才是实际的请求

难以启齿的正则

JS正则表达式

既然是正则那就先从字符串操作开始

search(‘xxx’)

  • 字符串操作返回查找字符串的位置
  • 没找到返回 -1
1
2
3
4
5
6
7
8
9
var str = 'abcdef';

console.log(str.search('a')) // 0
console.log(str.search('b')) // 1
console.log(str.search('c')) // 2
console.log(str.search('d')) // 3
console.log(str.search('e')) // 4

console.log(str.search('x')) // -1

substring()

口诀「包头不包尾」(左闭右开)

获取子字符串

1
2
3
4
5
var str = 'abcdef';
console.log(str.substring(2,5)) //cde
console.log(str.substring(1)) // bcdef
console.log(str.substring(6)) // ''空字符
console.log(str.substing(-1)) //abcdef

charAt()

获取某个字符

1
2
var str = 'abcdef';
console.log(str.charAt(3)) //d

split()

分割字符串,获取数组

1
2
3
var str = '13-14-aaa-xxx';
var arr = str.split('-');
console.log(arr) // [13,14,'aaa','xxx']

为什么要学正则

需求查找字符串里的数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var str = '12 fff 87 er334 233 -=-=fa80';
var arr = [];
var tmp = '';

for(var i=0;i<str.length;i++){
if(str.charAt(i) >= '0' && str.charAt(i) <= '9'){
tmp+=str.charAt(i);
}else{
if(tmp){
arr.push(tmp);
tmp = '';
}
}
}
console.log(arr) //['12','87','334','80']

if 正则

1
2
3
4
5
6
var str = '12 fff 87 er334 233 -=-=fa80';
var arr = [];

arr = str.match(/\d+/g)

console.log(arr) //['12','87','334','80']

什么是正则

一串英文、数字 @ - 一串英文、各种文 「计算机」是看不懂的

计算机只懂 0/1 、逻辑、程序 —->规则、模式

  • 强大的字符串匹配工具
  • 一种正常人类很难懂得文字
  • RegExp对象

正则就是干

  • 两种风格迥异的使用方式
需求1 看第一个例子查找字母 ‘a’
1
2
3
4
5
// js风格
var reg = new RegExp('a');
var str = 'abcdef';

console.log(str.search(reg)); // 0

另一种风格

1
2
3
4
// perl风格
var reg = /a/;
var str = 'abcdef';
console.log(str.search(reg)); // 0
需求2 查找忽略大小写的字母 ‘b’
忽略大小写之「i」(ignore)
1
2
3
4
5
// js风格
var reg = new RegExp('b','i');
var str = 'aBcdef';

console.log(str.search(reg)); // 0

另一种风格

1
2
3
4
// perl风格
var reg = /a/i;
var str = 'Abcdef';
console.log(str.search(reg)); // 0
search 和 match 的区别

search是查找匹配规则的字符(只找一次,找到匹配规则的第一个索引返回)

match 是返回所有匹配规则的东西都取出来

1
2
3
4
5
var reg = /\d/;
var str = 'asdf 34 657 cs33';
console.log(str.search(reg)) //5
alert(str.match(reg)) // 3
console.log(str.match(reg)) // ["3", index: 5, input: "asdf 34 657 cs33", groups: undefined]

match返回3是因为 计算机很蠢,你只告诉它找数字,没告诉它找几个

但是,正则天生懒惰想变勤奋你得加「g」

「g」global

那你就给我勤奋一点!

1
2
3
var reg = /\d/g;
var str = 'asdf 34 657 cs33';
console.log(str.match(reg)) // ["3", "4", "6", "5", "7", "3", "3"]

怎么出来的都是个位的数字?

因为你只告诉计算机取一个数字

量词(个数)
1
2
3
var reg = /\d+/g;
var str = 'asdf 34 657 cs33';
console.log(str.match(reg)) // ["34", "657", "33"]
replace()

把’a’替换成 0

1
2
3
//仅第一个a被替换了  
var str = 'abc aaa erv';
console.log(str.replace('a','0')) // 0bc aaa erv
  • replace 配合 字符串去替换字符是非常弱爆的
  • replace只有配合正则才能发挥真正的作用
1
2
3
4
var str = 'abc aaa erv';

var reg = /a/;
console.log(str.replace(reg,'0')) // 0bc aaa erv

但是正则有全局匹配啊

1
2
var reg2 = /a/g;
console.log(str.replace(reg2,'0')) // 0bc 000 erv
replace之敏感词过滤
1
2
3
4
var reg = /零售|中国|淘宝/g;
var str = '淘宝网是亚太地区较大的网络零售、商圈,由阿里巴巴集团在2003年5月创立。淘宝网 [1] 是中国深受欢迎的网购零售平台,拥有近5亿的注册用户数,每天有超过6000万的固定访客,同时每天的在线商品数已经超过了8亿件,平均每分钟售出4.8万件商品';

console.log(str.replace(reg,'**'))

元字符(方括号)

需求匹配 以a或b或c开头+ ‘pc’结尾的字符

1
2
3
[abc]pc
apc bpc cpc √
dpc epc fpc ×
1
2
3
var str = 'apc xpc ppc bpc spc tpc';
var reg = /[abc]pc/g;
console.log(str.match(reg)) // ["apc", "bpc"]

元字符之范围

  • 任意字符 [abc]
  • 范围 [a-z] [0-9]
  • 排除 [^a]
1
2
3
4
[a-z]   a到z的字母
[0-9] 相当于 \d 匹配数字
[^a-z] 除了a到z的字母
[^a-z0-9] 除了a到z的字母和数字

转义字符

1
2
3
4
5
6
7
.  点----任意字符
\d 数字0-9 [0-9]
\w 英文数字下划线 [a-z0-9_]
\s 空白字符
\D 非0-9 [^0-9]
\W 非字母数字下划线 [^a-z0-9_]
\S 非空白字符

偷小说之替换html标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var str = `<p id="p1">fdsadfdssafas</p>
<p class="p2">aaaaaaaaaaaa</p>
<p disabled>bbbbbbbbbbb</p>
<span>ccccccccccc</span>
<div>dddddddddddd</div>
<p>eeeeeeeeeeeee</p>`;

//你肯定想到的是
var reg = /<.+>/g; // 这样会把遇到的第一个 "<"一直匹配到最后一个">"

//实际上应该是除了 "<>"以外

var reg2 = /<[^<>]+>/g;
console.log(str.replace(reg2,''))

量词:个数

1
2
3
4
5
6
7
8
{n} 正好出现n次
{n,m} 最少n次,最多m次
{n,} 最少n次,最多不限

+ <===> {1,}
? <===> {0,1}

* <===> {0,} 可以可无 不推荐使用容易误导
需求1 电话号码 (除去区号010/022/0537)
1
[1-9]\d{7}
需求2 qq号(qq号没有0开头的) 5-11位
1
[1-9]\d{4,10}
需求3 固定电话 010-87490623-86
1
2
3
4
5
6
7
8
9
10
010-87490623-86
010是区号可有可无
86是分机号也是可有可无

前面的区号可有可无 (0\d{2,3}-)?
座机号8位 [1-9]\d{7}
分机号可有可无 (-\d{1,5})?

//最后
(0\d{2,3}-)?[1-9]\d{7}(-\d{1,5})?
为什么不推荐用「*」

因为匹配数字的时候0次也算在内

1
2
3
var str = '12 fff 85 er552 333 -=-=fa22';
console.log(str.match(/\d*/g))
// ["12", "", "", "", "", "", "85", "", "", "", "552", "", "333", "", "", "", "", "", "", "", "22", ""]
行首 「^」行尾「$」

test()

校验是否符合正则返回 true/false

校验邮箱
1
2
3
4
5
6
7
var str = 'trustfor@sina.cn'
var reg = /^\w+@[a-z0-9]+\.[a-z]+$/i;
if(reg.test(str)){
//合法
}else{
//你丫写错了
}