2020年360前端星计划课程笔记-0410

08 - 正则的三个使用场景

正则表达式的创建和使用

创建正则表达式

1.使用正则表达式字面量

const reg = /[a-z]\d+[a-z]/i
  • 优点
    • 简单方便
    • 不需要考虑二次转义
  • 缺点
    • 子内容无法重复使用
    • 过长的正则导致可读性差

2.使用RegExp构造函数

const alphabet = '[a-z]';
const reg = new RegExp(`${alphabet}\\d+${alphabet}`, 'i');  //内容,修饰符
  • 优点
    • 子内容可以重复使用
    • 可以通过控制子内容的粒度提高可读性
  • 缺点
    • 二次转义非常容易导致bug
const reg = new RegExp(`\d+`);  //reg = /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

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"
  • source返回当前正则表达式的模式文本的字符串

  • flags返回当前正则表达式的修饰符的字符串,按字母升序排序(gimsuy)

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

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
  • RegExp.prototype.exec 要求输入字符串,遇到非字符串类型会尝试转换

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

  • 匹配成功,返回匹配结果

  • 匹配失败,返回 null

  • 当正则表达式含有 g 修饰符时,RegExp.prototype.exec 每次只返回一个匹配结果,数据格式和不含 g 修饰符相同。

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

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

4.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]+/.test(‘a1’) === true

  • [0-9]、\d匹配数字

  • [a-z] 匹配小写字母

  • [\u4e00-\u9fa5] 匹配汉字

  • + 匹配一个或多个

/^\d+$/

  • 不能匹配带符号的数值,不能匹配小数

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

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

/^[+-]?\d+(\.\d+)?$/

  • 不能匹配无整数部分的小数,捕获组会带来额外开销

  • () 捕获组

  • ? 作为限定符时表示匹配0到1个

  • . 匹配除换行符外任意字符

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

  • 不能匹配无小数部分的数值(2.),不能匹配科学计数法

  • (?:)非捕获组

  • * 匹配0个或多个

完整的数值正则

2020年360前端星计划课程笔记-0410_第1张图片

​ 这个 token 是 CSS 的 token,在 javascript 中,要多考虑一种情况

+'2.'; // 2
+'2.e1'; // 20

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

  • | 创建分支,或
  • i 修饰符 匹配时忽略大小写
数值的解析
const reg = /[+-]?(?:\d*\.)?\d+(?:e[+-]?\d+)?(?=px|\s|$)/gi;
  • x(?=y) 仅匹配被y跟随的x
  • x(?!y) 仅匹配不被y跟随的x
  • (?<=y)x x只有在y后面才匹配
  • (?
数值转货币格式
const reg = /(\d)(?=(\d{3})+(,|$))/g;
function formatCurrency(str) {
   return str.replace(reg, '$1,');
}
  • {n} 表示重复n次,n必须是非负整数
  • {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})$`);
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个捕获组
  • \s 匹配空白符
  • rgb(r, g, b, a)和rgba(r, g, b)是合法的
  • 当捕获组内的内容是可选的时候,一定要把问号写在捕获组内
  • 如果可选内容的圆括号不可省略,如(a|b|c)?,应该多嵌套一层:((?:a|b|c)?)
hsl/hsla表示法、颜色名表示法
/* hsl & hsla */
color: hsl(h, s%, l%);
color: hsla(h, s%, l%, a);
color: hsla(h, s%, l%, a%);

/* keywords */
color: red;
color: blue;
/* …… */
正则处理颜色
const hex = '[0-9a-z]';
const hexReg = new RegExp(`^#(?${hex})\\k(?${hex})\\k(?${hex})\\k(?${hex}?)\\k$`, 'i');
function shortenColor(str) {
    return str.replace(hexReg, '#$$$$');
}

console.log(shortenColor('#336600')); // '#360'
console.log(shortenColor('#19b955')); // '#19b955'
console.log(shortenColor('#33660000')); // '#3600'
  • (?)
    • 具名捕获组
    • 反向引用时语法为 \k
    • replace时,使用$访问具名捕获组
    • 应用exec时,具名捕获组可以通过 execResult.groups[key] 访问

正则与URL

完整URL规范

img

解析URL

const protocol = '(?https?:)';
const host = '(?(?[^/#?:]+)(?::(?\\d+))?)';
const path = '(?(?:\\/[^/#?]+)*\\/?)';
const search = '(?(?:\\?[^#]*)?)';
const 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: '',
    };
}

解析search和hash

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;
}
  • *? ?跟在任意限定符之后,表示非贪婪模式
  • y 粘连修饰符,全局匹配
    • y 修饰符每次匹配的结果必须是连续的
    • y 修饰符在 match 时只会返回第一个匹配结果

09/10 - Node.js基础入门

Node.js与JavaScript的区别
  • 基于异步 I/O 相关接口
  • 基于 node_modules 和 require 的模块依赖
  • 提供 C++ addon API 与系统交互
Node.js可以干什么
  • Web 服务端:Web Server、爬虫
  • CLI 命令行脚本:webpack
  • GUI 客户端软件:VSCode、网易云音乐
  • IoT, 图像处理, 实时通讯,加密货币…
模块
  • 内置模块:编译进 Node 中,例如 http fs net process path 等
  • 文件模块:原生模块之外的模块,和文件(夹)一一对应
  • 模块类型:.js, .json, .node, .mjs, …
模块路径查找
  • 绝对路径
  • 相对路径
    • 和当前路径处理为绝对路径
  • 模块/文件夹
    • 原生模块,直接读取缓存
    • [$NODE_PATH, ~/.node_modules,
      ./node_modules, …/node_modules, …]
    • 解析 package.json,查找 main 属性,没有则使用 index.js
    • 如果未找到,则报错
模块缓存
  • 模块加载后会将返回值缓存起来
  • 下次加载时直接读取缓存结果,避免文件 I/O 和解析时间
  • 导出对象缓存在 Module._cache 对象上

NPM(Node Package Manager)

包管理
  • 一个package.json文件应该存在于包顶级目录下
  • 二进制文件应该包含在bin目录下
  • JavaScript代码应该包含在lib目录下
  • 文档应该在doc目录下
  • 单元测试应该在test目录下

基于Node.js的Web开发

Koa 无规范约束,不利于团队开发,中间件繁多,质量参差不齐,选择困难

Thinkjs

Node.js调试

  • 日志调试
  • 断点调试
    • node --inspect
    • vscode
    • ndb

Node开发角色转换

  • 前端

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

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

你可能感兴趣的:(2020年360前端星计划课程笔记-0410)