判断是否是合法的中国大陆手机号。

正则 GitHub 来源:https://github.com/VincentSit/ChinaMobilePhoneNumberRegex

1
2
3
4
const isValidChinaMobilePhoneNumber = tel =>
/^(?:\+?86)?1(?:3\d{3}|5[^4\D]\d{2}|8\d{3}|7(?:[35678]\d{2}|4(?:0\d|1[0-2]|9\d))|9[189]\d{2}|66\d{2})\d{6}$/.test(
tel,
);

测试用例:测试框架使用 ava

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// 所有正确的前缀
const correctPrefix = [
// 移动
'1340',
'1341',
'1342',
'1343',
'1344',
'1345',
'1346',
'1347',
'1348',
'135',
'136',
'137',
'138',
'139',
'150',
'151',
'152',
'157',
'158',
'159',
'178',
'182',
'183',
'184',
'187',
'188',
'198',
// 联通
'130',
'131',
'132',
'155',
'156',
'166',
'175',
'176',
'185',
'186',
// 电信
'133',
'1349',
'153',
'173',
'17400',
'17401',
'17402',
'17403',
'17404',
'17405',
'177',
'180',
'181',
'189',
'191',
'199',
// 海事卫星通信
'1749',
// 应急通信
'17406',
'17407',
'17408',
'17409',
'17410',
'17411',
'17412',
];

// 产生[a,b]的随机整数
const generateNumber = (a, b) => Math.floor(Math.random() * (b - a + 1) + a);
const n = 100; // 每个 scheme 生成 100个随机电话

// 产生基于以上前缀的随机电话号码,每个前缀模式产生 100(n) 个
const generateRandomPhoneNumber = prefix => {
const result = [];
for (let i = 0; i < prefix.length; i++) {
// 需要生成的数字的长度
let length = 11 - prefix[i].length;
// 生成 n 个长度为 length 的数字
for (let j = 0; j < n; j++) {
// 生成长度为 n 的数字
let current = '';
for (let k = 0; k < length; k++) {
current += generateNumber(0, 9);
}
result.push(prefix[i] + current);
}
}
return result;
};

// 分别产生 10000 个 3 位 4 位和 5 位不满足前缀的电话号码
const generatePrefix = length => {
const m = 1000;
const result = [];
// 生成 m 个长度为 length 的数字
for (let j = 0; j < m; j++) {
// 生成长度为 n 的数字
let current = '';
for (let k = 0; k < length; k++) {
current += generateNumber(0, 9);
}
result.push(current);
}
return result.filter(item => correctPrefix.indexOf(item) === -1);
};

const prefix3 = generatePrefix(3);
const prefix4 = generatePrefix(4);
const prefix5 = generatePrefix(5);

test('测试手机号是否合法', t => {
// plan
t.plan(4);
// true
t.true(
generateRandomPhoneNumber(correctPrefix).every(item => isValidChinaMobilePhoneNumber(item)),
'',
);
t.true(
generateRandomPhoneNumber(prefix3)
.filter(item => correctPrefix.every(value => !item.startsWith(value)))
.every(item => !isValidChinaMobilePhoneNumber(item)),
'',
);

t.true(
generateRandomPhoneNumber(prefix4)
.filter(item => correctPrefix.every(value => !item.startsWith(value)))
.every(item => !isValidChinaMobilePhoneNumber(item)),
'',
);

t.true(
generateRandomPhoneNumber(prefix5)
.filter(item => correctPrefix.every(value => !item.startsWith(value)))
.every(item => !isValidChinaMobilePhoneNumber(item)),
'',
);
});