小宋爱睡觉 小宋爱睡觉
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
  • 手写系列
  • Promise
  • 场景应用
  • 数组的方法
  • 正则表达式相关
    • 将数字每千分位用逗号隔开
    • 统计一段文字中出现最多的单词及其出现次数
    • 模版引擎
    • 实现loadash._get
    • 匹配十六进制颜色
    • RGB转#FFF
    • 判断url只包含qq.com
    • 匹配时间
    • 匹配dom节点的id
    • 验证密码
    • 模拟trim方法
    • 将每个单词的首字母大写
    • 驼峰化
  • Vue手写
  • 手写系列
Crucials
2021-11-28

正则表达式相关

# 正则表达式相关手写

# 将数字每千分位用逗号隔开

var string1 = "12345678",
string2 = "123456789";
reg = /(?!^)(?=(\d{3})+$)/g;

var result = string1.replace(reg, ',')
console.log(result); 
// => "12,345,678"

result = string2.replace(reg, ',');
console.log(result); 
// => "123,456,789"

// 用js
const split = (str) => {
  const res = [];
  let interger = str.split(".")[0];
  let decimal = str.split(".")[1];
  let s = "";
  for (let i = interger.length - 1; i >= 0; i--) {
    let len = interger.length - i;
    s = interger[i] + s;
    if (len % 3 === 0 || i === 0) {
      res.unshift(s);
      s = "";
    }
  }
  if (decimal?.length) {
    return res.join(",") + `.${decimal}`;
  }
  return res.join(",");
};

console.log(split("123456789.1234566"));
console.log(split("123456789"));

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

# 统计一段文字中出现最多的单词及其出现次数

function getMostFrequentWord(text) {
  const words = text
    .toLowerCase() // 不区分大小写
    .replace(/[^\w\s]/g, '') // 去除标点符号
    .split(/\s+/); // 按空格分词

  const freqMap = {};

  for (const word of words) {
    if (!word) continue;
    freqMap[word] = (freqMap[word] || 0) + 1;
  }

  let maxWord = '';
  let maxCount = 0;

  for (const [word, count] of Object.entries(freqMap)) {
    if (count > maxCount) {
      maxWord = word;
      maxCount = count;
    }
  }

  return { word: maxWord, count: maxCount };
}

const result = getMostFrequentWord("This is a test. This test is only a test.");
console.log(result); // { word: 'test', count: 3 }
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

# 模版引擎

function render(template, data) {
  const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
  if (reg.test(template)) {
    // 判断模板里是否有模板字符串
    const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
    template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
    return render(template, data); // 递归的渲染并返回渲染后的结构
  }
  return template; // 如果模板没有模板字符串直接返回
}
let template = "我是{{name}},年龄{{age}},性别{{sex}}";
let data = {
  name: "姓名",
  age: 18,
};
render(template, data); // 我是姓名,年龄18,性别undefined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 实现loadash._get

function _get(source, path, defaultValue = undefined) {
  // 将数组格式的路径转化成dot格式的,再拆分成key数组
  // a[0].b -> a.0.b -> ['a', '0', 'b']
  const paths = path.replace(/\[(\d+)\]/g, ".$1").split(".");

  let result = source;
  for (const p of paths) {
    result = Object(result)[p]; // null 与 undefined 取属性会报错, 用Object包装一下
  }
  return result || defaultValue;
}
const object = { a: [{ b: { c: 3 } }] };

console.log(_get(object, "a[0].b.c"));
// => 3

console.log(_get(object, "a.b.c", "default"));
// => 'default'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 匹配十六进制颜色

表示一个16进制字符,可以用字符组[0-9a-fA-F]。

其中字符可以出现3或6次,需要是用量词和分支结构

const reg = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;

var string = "#ffbbad #Fc01DF #FFF #ffE";
console.log(string.match(reg));
// [ '#ffbbad', '#Fc01DF', '#FFF', '#ffE' ]
1
2
3
4
5

# RGB转#FFF

// 1. 利用 match() 方法,读取出 r 、 g 、 b
function rgb2hex(sRGB) {
    var rgb = sRGB.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
    return rgb.reduce((acc, cur) => {
        var hex = (cur < 16? '0':'') + Number(cur).toString(16)
        return acc + hex
    }, '#').toUpperCase()
}

// 测试
rgb2hex('rgb(255, 255, 255)')
// "#FFFFFF"
rgb2hex('rgb(16, 10, 255)')
// "#100AFF"

// 2. rgb(255, 255, 255) 中 r 、 g 、 b 分别为连续的数字,所以我们可以利用正则 /\d+/g 获取取所有连着的数字
function rgb2hex(rgb) {
    const rgb = rgb.match(/\d+/g);
    const hex = (n) => {
        return ("0" + Number(n).toString(16)).slice(-2);
    }
    return rgb.reduce((acc, cur) => acc + hex, '#').toUpperCase()
}

// 测试
rgb2hex('rgb(255, 255, 255)')
// "#FFFFFF"
rgb2hex('rgb(16, 10, 255)')
// "#100AFF"

// 3. 观察 rgb(255, 255, 255) 的每一个色值是透过 , 连接一起的,所以我们考虑是否能通过 split(',') 拆分出每一个色值,主要考虑两步

替换 rgb(255, 255, 255) 的部分字符( rgb 、 ( 、 ) )为 ''
拆分出每一个色值
function rgb2hex(sRGB) {
    const rgb = sRGB.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
    return "#" + ((1 << 24) + (Number(rgb[0]) << 16) + (Number(rgb[1]) << 8) + Number(rgb[2])).toString(16).slice(1).toUpperCase()}

// 测试
rgb2hex('rgb(255, 255, 255)')
// "#FFFFFF"
rgb2hex('rgb(16, 10, 255)')
// "#100AFF"
rgb2hex('rgb(1, 2, 3)')
// "#010203"
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

# 判断url只包含qq.com

http://www.qq.com  // 通过

http://www.qq.com.cn  // 不通过

http://www.qq.com/a/b  // 通过

http://www.qq.com?a=1  // 通过

http://www.123qq.com?a=1  // 不通过

'http://www.baidu.com?redirect=http://www.qq.com/a' // 不通过
1
2
3
4
5
6
7
8
9
10
11
function check(url){
  if(/^https?:\/\/\w+\.qq\.com[^.]*$/.test(url)){
    return true;
  }else{
    return false;
  }

}
check('http://www.qq.com')
// true

check('http://www.qq.com.cn')
// false

check('http://www.qq.com/a/b')
// true

check('http://www.qq.com?a=1')
// true

check('http://www.123qq.com?a=1')
// false

check('http://www.baidu.com?redirect=http://www.qq.com/a')
// false
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

# 匹配时间

匹配23:59 02:07 7:9

const regex = /^(0?[0-9]|1[0-9]|2[0-3]):(0?[0-9]|[1-5][0-9])$/;

console.log(regex.test("23:59"));
console.log(regex.test("02:07"));
console.log(regex.test("7:9"));
1
2
3
4
5

# 匹配dom节点的id

要求从

<div id="container" class="main"></div>

提取出id="container"

const regex = /id=".*?"/;
const str = '<div id="container" class="main"></div>';
console.log(str.match(regex));
// 或者

var regex = /id="[^"]*"/;
const str = '<div id="container" class="main"></div>';
console.log(str.match(regex));
1
2
3
4
5
6
7
8

# 验证密码

密码长度6-12位,由数字、小写字符和大写字母组成,但必须至少包括2种字符。

var reg = /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9A-Za-z]{6,12}$/;
console.log( reg.test("1234567") ); // false 全是数字
console.log( reg.test("abcdef") ); // false 全是小写字母
console.log( reg.test("ABCDEFGH") ); // false 全是大写字母
console.log( reg.test("ab23C") ); // false 不足6位
console.log( reg.test("ABCDEF234") ); // true 大写字母和数字
console.log( reg.test("abcdEF234") ); // true 三者都有
1
2
3
4
5
6
7

或者使用?!p

// 不能只出现数字 和 不能只出现小写字母和不能只出现大写字母
var reg = /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/;
console.log( reg.test("1234567") ); // false 全是数字
console.log( reg.test("abcdef") ); // false 全是小写字母
console.log( reg.test("ABCDEFGH") ); // false 全是大写字母
console.log( reg.test("ab23C") ); // false 不足6位
console.log( reg.test("ABCDEF234") ); // true 大写字母和数字
console.log( reg.test("abcdEF234") ); // true 三者都有
1
2
3
4
5
6
7
8

# 模拟trim方法

function trim(str) {
	return str.replace(/^\s+|\s+$/g, '');
}
console.log( trim("  foobar   ") ); 
// => "foobar"
1
2
3
4
5

# 将每个单词的首字母大写

?:是非捕获分组

看栗子

var regex = /(?:ab)+/g;
var string = "ababa abbb ababab";
console.log( string.match(regex) ); 
// => ["abab", "ab", "ababab"]
function titleize(str) {
	return str.toLowerCase().replace(/(?:^|\s)\w/g, function(c) {
		return c.toUpperCase();
	});
}
console.log( titleize('my name is epeli') ); 
// => "My Name Is Epeli"
1
2
3
4
5
6
7
8
9
10
11

# 驼峰化

function camelize(str) {
	return str.replace(/[-_\s]+(.)?/g, function(match, c) {
		return c ? c.toUpperCase() : '';
	});
}
console.log( camelize('-moz-transform') ); 
// => "MozTransform"

// 或者
function camelize(str) {
  return str.replace(/[-_\s](\w)/g, (_, c) => c.toUpperCase());
}
1
2
3
4
5
6
7
8
9
10
11
12
上次更新: 2025/05/27, 15:44:05
数组的方法
Vue手写

← 数组的方法 Vue手写→

Copyright © 2021-2025 粤ICP备2021165371号
  • 跟随系统
  • 浅色模式
  • 深色模式