360前端星计划学习笔记0410

360前端星计划学习笔记(五)正则的三个应用场景–王峰老师
360前端星计划学习笔记(六)NodeJS基础入门

正则

正则表达式的创建和使用

创建正则表达式的两种方式

字面量

const reg=/[a-z]\d+[a-z]/i

优点:①简单方便;②不需要考虑二次转义;

缺点:①子表达式无法复用②过长的正则可读性降低

使用RegExp构造函数

const alphabet='[a-z]'
const reg = new RegExp(`${alphabet}\\d+${alphabet}`,'i')

需要注意\d使用转义

优点:①子内容可以重复使用;②可以通过控制子内容的粒度提高可读性

缺点:二次转义的问题非常容易导致bug

const reg = new RegExp(`\d`)
reg.test('1')//false
reg.test('ddd')//true
正则表达式的常见用法
  1. RegExp.prototype.test()

    const reg = /[a-z]\d+[a-z]/i;
    
    reg.test('a1a'); // true
    reg.test('1a1'); // false
    reg.test(Symbol('a1a')); // TypeError
    

    内容如果无法隐式转为字符串会抛出TypeError

  2. RegExp.prototype.source和RegExp.prototype.flags

    const reg = /[a-z]\d+[a-z]/ig;
    
    reg.source; // "[a-z]\d+[a-z]"
    reg.flags; // "gi"
    
    • RegExp.prototype.source

      返回当前正则表达式的模式文本的字符串

    • RegExp.prototype.flags

      es2015新增,返回当前正则表达式的修饰符的字符串,会对修饰符按照字母升序进行排序(gimsuy)

  3. RegExp.prototype.exec()和String.prototype.match()

    输入输出

    • 输入:

      RegExp.prototype.exec 要求输入字符串,遇到非字符串类型会尝试转换

      String.prototype.match 要求输入正则表达式,遇到其它类型会先尝试转成字符串,再以字符串为 source 创建正则表达式

  • 输出

    匹配成功,返回匹配结果

    匹配失败,返回 null

   const reg = /[a-z]\d+[a-z]/i;

   reg.exec('a1a'); // ["a1a", index: 0, input: "a1a", groups: undefined]
reg.exec('1a1'); // null
   'a1a'.match(reg); // ["a1a", index: 0, input: "a1a", groups: undefined]
'1a1'.match(reg); // null
   
   const reg1 = /(a)/g;
   
   reg1.exec('a1a'); // ["a", "a", index: 0, input: "a1a", groups: undefined]
   'a1a'.match(reg1); // ["a", "a"]
  • 特殊:当正则表达式含有 g 修饰符时,RegExp.prototype.exec 每次只返回一个匹配结果,数据格式和不含 g 修饰符相同。

    String.prototype.match 会返回所有的匹配结果,数据格式会变为字符串数组。

    由于 String.prototype.match 返回的数据格式不固定,因此大多数情况都建议使用 RegExp.prototype.exec

  1. RegExp.prototype.lastIndex;
 const reg = /(a)/g;
 const str = 'a1a';
 
 reg.lastIndex; // 0
 reg.exec('a1a'); // ["a", "a", index: 0, input: "a1a", groups: undefined]
 reg.lastIndex; // 1
 reg.exec('a1a'); // ["a", "a", index: 2, input: "a1a", groups: undefined]
 reg.lastIndex; // 3
 reg.exec('a1a'); // null
 reg.lastIndex; // 0

当前正则表达式最后一次匹配成功的结束位置(也就是下一次匹配的开始位置)

注意:lastIndex 不会自己重置,只有当上一次匹配失败才会重置为 0 ,因此,当你需要反复使用同一个正则表达式的时候,请在每次匹配新的字符串之前重置 lastIndex!

5.String.prototype.replace()、String.prototype.search()、String.prototype.split()

'a1a'.replace(/a/, 'b'); // 'b1a'
'a1a'.replace(/a/g, 'b'); // 'b1b'

'a1a'.search(/a/); // 0
'a1a'.search(/a/g); // 0

'a1a'.split(/a/); // ["", "1", ""]
'a1a'.split(/a/g); // ["", "1", ""]

场景一:正则与数值

数值判断
/[0-9]+/

[] 字符集,使用连字符 - 表示指定的字符范围,如果想要匹配连字符,需要挨着方括号放置,或进行转义,0-9 表示匹配从 0 到 9 的数字字符,常用的还有 a-z 匹配小写字母,\u4e00-\u9fa5 匹配汉字等,如果只是匹配数字,还可以使用字符集缩写 \d

+ 限定符 一个或多个

该表达式缺点:不是全字符匹配,存在误判,如 /[0-9]+/.test(‘a1’) === true

/^\d+$/

^匹配字符串开始位置,当结合 m 修饰符时,匹配某一行开始位置

$匹配字符串结束位置,当结合 m 修饰符时,匹配某一行结束位置

该表达式缺点

不能匹配带符号的数值,如+1,-2

不能匹配小数,如:3.14159

/1?\d(.\d+)?$/

() 圆括号内是一个子表达式,当圆括号不带任何修饰符时,表示同时创建一个捕获组
?在正则中有多种含义,作为限定符时,表示匹配零到一个
\. .可以匹配除换行符之外的任意字符,当结合s修饰符时,可以匹配包括换行符在内的任意字符
该表达式缺点:不能匹配无整数部分的小数,如.123会匹配失败;捕获组会有额外的开销

/2?(?:\d*.)?\d+$/

(?:) 创建一个非捕获组

*限定符,匹配零个或多个

缺点:不能匹配无小数部分的数值;不能匹配科学计数法,如 1e2、3e-1、-2.e+4

完整的数值正则

在这里插入图片描述

/^[+-]?(?:\d+\.?|\d*\.\d+)(?:e[+-]?\d+)?$/i

用正则处理数值
数值的解析
const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;

function execNumberList(str) {
    reg.lastIndex = 0;
    let exec = reg.exec(str);
    const result = [];
    while (exec) {
        result.push(parseFloat(exec[0]));
        exec = reg.exec(str);
    }
    return result;
     // let array=str.split(" ");
    // res=array.map(item=>parseFloat(item,10));
    // return res.length?res.join(','):null //不会用正则的我
}

console.log(execNumberList('1.0px .2px -3px +4e1px')); // [1, 0.2, -3, 40]
console.log(execNumberList('+1.0px -0.2px 3e-1px')); // [1, -0.2, 0.3]
console.log(execNumberList('1px 0')); // [1, 0]
console.log(execNumberList('-1e+1px')); // [-10]

(?=expression)

正向肯定环视 / 顺序肯定环视 / 先行断言

用于匹配符合条件的位置, 匹配到位置为止

类似的语法还有:

(?!expression) 正向否定环视 / 顺序否定环视 / 先行否定断言

(?<=expression) 反向肯定环视 / 逆序肯定环视 / 后行断言,es2018 新增

(?<!expression) 反向否定环视 / 逆序否定环视 / 后行否定断言,es2018 新增

g

全局匹配,用于取出目标字符串中所有符合条件的结果

需要注意的点:

  • 按照 CSS 规范,只有数值为 0 才可以省略单位,这种情况没有必要靠正则来过滤
  • 这个例子中只验证了 px 单位,实际还存在 pt、em、vw 等单位,并且没有考虑百分比的情况
  • 实际工作中,要根据需求追加处理逻辑

数值转货币格式

//数值转货币
function formatCurrency(str) {
    // ……
     const reg=/(\d)(?=(\d{3})+(,|$))/g
     return str.replace(reg,`$1,`)
 }
// js方式
 function formatCurrency1(str) {
    // ……
    let res=''
    let count=0;
    for(let i=str.length-1;i>=0;i--){
       if(count==2&&i!=0){
           res=','+str[i]+res;
           count=-1;
       }else{
           res=str[i]+res
       }
       count++;
    }
    return res;
 }
const reg = /(\d)(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$1,');
}

{n}

限定符,表示重复 n 次,n 必须是非负整数

类似的语法还有:

{n, m} 表示重复 n 到 m 次,n 和 m 都必须是非负整数,且 n <= m

{n,} 表示重复 n 次以上

$n

用于 replace 的字符串中,表示第 n 个捕获组,n 可以从 1 到 9

$& 表示本次完整的匹配,所以这段代码还可以改写为:

const reg = /\d(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$&,');
}

在ES2018以上的环境,还可以使用反向环视

const reg = /(?<=\d)(?=(?:\d{3})+(?:,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, ',');
}

其它注意事项

环视中的圆括号也会生成捕获组,所以都要采用 (?😃 的非捕获组形式

其它注意事项**

环视中的圆括号也会生成捕获组,所以都要采用 (?😃 的非捕获组形式

场景二:正则与颜色

16进制表示法
color: #rrggbb;
color: #rgb;
color: #rrggbbaa;
color: #rgba;

对应的正则写法

const hex = '[0-9a-fA-F]';
const reg = new RegExp(`^(?:#${hex}{6}|#${hex}{8}|#${hex}{3,4})$`);

其它注意事项

  • 也可以使用 i 修饰符来匹配大小写,i 修饰符和 a-fA-F 要根据实际需求来做取舍
  • 还记得前面的问题吗?
rgb/rgba表示法
color: rgb(r, g, b);
color: rgb(r%, g%, b%);
color: rgba(r, g, b, a);
color: rgba(r%, g%, b%, a);
color: rgba(r, g, b, a%);
color: rgba(r%, g%, b%, a%);

对应的正则写法:

const num = '[+-]?(?:\\d*\\.)?\\d+(?:e[+-]?\\d+)?';
const comma = '\\s*,\\s*';
const reg = new RegExp(`rgba?\\(\\s*${num}(%?)(?:${comma}${num}\\1){2}(?:${comma}${num}%?)?\\s*\\)`);

\n反向引用,表示引用第 n 个捕获组

由于 r/g/b 必须同时为数值或百分比,所以 %? 只需要捕获一次,用 \1 来引用

\s字符集缩写,用于匹配空白

需要注意的点

  • 按照规范,rgb(r,g,b,a) 和 rgba(r,g,b) 也是合法的
  • r/g/b 的值应该是 0~255 的整数,但是溢出或小数并不会报错
  • 当捕获组内的内容是可选的时候,一定要把问号写在捕获组内
    如果可选内容的圆括号不可省略,如(a|b|c)?,应该多嵌套一层:((?:a|b|c)?)
  • 尽可能不让捕获组是可选的
hsl

更多颜色表示法:https://www.w3.org/TR/css-color/

用正则处理颜色
 //正则缩短16进制颜色值
const hex = '[0-9a-z]';
const hexReg = new RegExp(`^#(?<r>${hex})\\k<r>(?<g>${hex})\\k<g>(?<b>${hex})\\k<b>(?<a>${hex}?)\\k<a>$`, 'i');
function shortenColor(str) {
    return str.replace(hexReg, '#$<r>$<g>$<b>$<a>');
}

console.log(shortenColor('#336600')); // '#360'
console.log(shortenColor('#19b955')); // '#19b955'
console.log(shortenColor('#33660000')); // '#3600'

(?)

  • es2018 新增,具名捕获组
  • 反向引用时的语法为 \k
  • 在 replace 中,使用 $ 来访问具名捕获组
  • 当应用 exec 时,具名捕获组可以通过 execResult.groups[key] 访问
const hex = '[0-9a-z]';
const hexReg = new RegExp(`^#(?<r>${hex})\\k<r>(?<g>${hex})\\k<g>(?<b>${hex})\\k<b>(?<a>${hex}?)\\k<a>$`, 'i');

hexReg.exec('#33660000');
// ["#33660000", "3", "6", "0", "0", index: 0, input: "#33660000", groups: {r: "3", g: "6", b: "0", a: "0"}]

场景三:正则与URL

用正则解析URL

在这里插入图片描述
protocol: 'http:'协议

host: ‘www.360.cn’ 域名

hostname: ‘www.360.cn’, 域名不包括port

port: ‘’, 端口

pathname: ‘’, search前域名后

search: ‘’, ?。。。

hash: ‘’#。。。

//解析URL
const protocol = '(?<protocol>https?:)';//具名捕获组
const host = '(?<host>(?<hostname>[^/#?:]+)(?::(?<port>\\d+))?)';
const path = '(?<pathname>(?:\\/[^/#?]+)*\\/?)';
const search = '(?<search>(?:\\?[^#]*)?)';
const hash = '(?<hash>(?:#.*)?)';
const reg = new RegExp(`^${protocol}\/\/${host}${path}${search}${hash}$`);
function execURL(url) {
    const result = reg.exec(url);
    if (result) {
        result.groups.port = result.groups.port || '';
        return result.groups;
    }
    return {
        protocol: '', host: '', hostname: '', port: '',
        pathname: '', search: '', hash: '',
    };
}

console.log(execURL('https://www.360.cn'));
console.log(execURL('http://localhost:8080/?#'));
console.log(execURL('https://image.so.com/view?q=360&src=srp#id=9e17bd&sn=0'));
console.log(execURL('this is not a url'));

注意事项

  • port 捕获组可能为 undefined
  • 要考虑解析失败的情形
用正则解析Search
function execUrlParams(str) {
    str = str.replace(/^[#?&]/, '');
    const result = {};
    if (!str) {
        return result;
    }
    const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;
    let exec = reg.exec(str);
    while (exec) {
        result[exec[1]] = exec[2];
        exec = reg.exec(str);
    }
    return result;
}

console.log(execUrlParams('#')); // { }
console.log(execUrlParams('##')); // { '#': '' }
console.log(execUrlParams('?q=360&src=srp')); // { q: '360', src: 'srp' }
console.log(execUrlParams('test=a=b=c&&==&a=')); // { test: 'a=b=c', '': '=', a: '' }

? 可以跟在任何限定符之后,表示非贪婪模式(注意:这个例子其实不太恰当,使用贪婪模式效果是一样的)

const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;

yes6 新增,粘连修饰符,和 g 修饰符类似,也是全局匹配。区别在于:

  1. y 修饰符每次匹配的结果必须是连续的
  2. y 修饰符在 match 时只会返回第一个匹配结果

其它注意事项

正则表达式如果可能匹配到空字符串,极有可能造成死循环,所以这段代码很重要:

if (!str) { return result; }

或者使用:lastIndex去判断值有没有变化,结果没往后走,如果没变就跳出。

作业:

function getUrlParam(str, key) {
     //
    str = str.replace(/^[#?&]/, '');
    const result = {};
    if (!str) {
        return result;
    }
    const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y;
    let exec = reg.exec(str);
    while (exec) {
        result[exec[1]] = exec[2];
        exec = reg.exec(str);
    }
    return result[key] || '';
}

console.log(getUrlParam('?nothing', 'test')); // ''
console.log(getUrlParam('#a=1&aa=2&aaa=3', 'a')); // '1'
console.log(getUrlParam('&b=1&a=1&b=2', 'b')); // '2'
console.log(getUrlParam('a=1&b=2&c=&d', 'c')); // ''
console.log(getUrlParam('&d==', 'd')); // '='

注意事项

  • 存在多个重复的 key 时,要求只返回最后一条匹配的结果

  • 挑战1:解法不止一种,你可以写出尽可能多的解法吗?

  • 挑战2:可以写出尽可能短的正则表达式吗?

    未完待续。。。

总结

明确需求

考虑全面

反复测试

NodeJS

NodeJS简介

与JavaScript的区别:

基于异步I/O相关接口

基于node——moudules和require 模块依赖

提供C++ addon API

可以做什么?

Web

IOT

Puppeteer sandbox

Node.js基础

模块
  • 内置模块:编译进Node中,http,fs,net,process,path
  • 文件模块:原生模块之外的模块,和文件(夹)一一对应

require/exports

模块类型

.js

.json

.node

.mjs

.cjs(common.js 导入导出形式)

模块路径查找
js模块解析

require

同步拿到文件内容,对内容进行闭包包装,会传入exports,require,module等

通过在虚拟沙盒中执行,

模块缓存

读取缓存对象

NPM

NPM 包管理器

包管理:

  • 一个package.json
  • 二进制文件应该
package.json
  • main:指定入口文件(默认根目录index.js文件)

  • scripts 脚本执行的快捷方式

  • 五个依赖家族角色

    • dependencies
    • devDependencies(开发时使用的包,别人安装不需要安装的包)
    • peerDependencies(需要)
    • bundledDependencies(捆绑安装其他包)
    • optionalDependencies(可选)
  • bin: 可以指定:k-v 快捷执行对应的文件

  • samver-version 小版本:bug 补丁 中版本新特性 大版本 代码重构,和之前版本有冲突或不兼容

  • registry 代理,指定源

包依赖

^1.2.2允许中小版本的更新

~0.7.0(0.7.x)接收小版本更新 可以接收0.7.6 不能接收0.8.0

*接收任意版本

不带任何,只该版本

NPM 问题

速度问题

安全问题(投毒,删了依赖其他包无法使用等)

  • 查看源码看Star
  • 外部的检测服务
  • npm audit

基于Node.js的Web开发

const http=require('http')
const server = http.createServer((req.res)=>{
res.end("Hello world");
})
server.listen(3000)
Koa框架

中间件挂载

用户请求像流水线一样被中间件一个一个执行修改,

源码:4个文件

use方法

原理:middleware提供接口,处理

ThinkJS

企业级目录规范

包括常用的模块
在这里插入图片描述

使用ThinkJS做TODO

数据校验:Logic机制专门用来支持数据校验(用户校验,权限校验)

文件和Action与controller 一一对应

todo:实际建立工程

NodeJS调试

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

日志调试 console.log()

断点调试

  • node --inspect NodeJS 6.3+ 在chrome\\inspect

  • vscode F5

  • ndb(好处,可以接在任意命令启动调试,在ndb可以编写修改,可以存储到文件,可以边调试边修改)

Node 开发角色转换

  • 前端

    • 跟浏览器打交道,兼容性问题
    • 组件化
    • 加载速度、JS 执行性能、渲染性能
    • 错误监控
    • XSS、CSRF 等安全漏洞
  • 服务端

    • 数据库、Redis 等周边服务
    • 性能、内存泄露、CPU、机器管理
    • 服务监控、错误监控、流量监控、报警
    • SQL注入、目录遍历等安全漏洞

  1. +- ↩︎

  2. +- ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值