功能说明
该示例把用户输入的电话号码整理成 E.164 格式,即加号开头、只含数字、总长 8 到 15 位。它支持带加号的国际号码、以 00 开头的国际拨号前缀,以及需要补默认国家区号的本地号码。结果可以直接存储、比较或传给短信服务商。
关键代码
normalizePhone 先校验输入为字符串并查询默认国家的拨号代码。去掉所有非数字字符后,根据是否以加号开头、是否以 00 开头分别处理:00 前缀直接去掉,本地号码则去掉前导零并补上默认区号。随后校验长度范围与首位不能为零,最后返回加号加数字。表驱动的方式让新增国家只需要补充代码映射。
使用注意
内置国家表只覆盖少量示例,生产环境应使用完整的 E.164 数据或 libphonenumber。该函数不做运营商归属、号码有效性或短信可达性校验。分机号、短号与紧急号码会被拒绝或产生错误结果。默认国家必须由用户明确选择,不能根据浏览器语言猜测。格式化后的号码仍应在服务端重新校验。
验证方式
断言美国本地号码 (415) 555-0132 规范化为 +14155550132,英国加号号码保持 +442079460958,00 开头的德国号码变为 +493012345678。测试中国本地号码补 86 并去掉前导零。再验证空串、过短、以零开头的国际号码与不支持的国家分别抛错。
代码示例
const DIAL_CODES = {
US: "1",
GB: "44",
CN: "86",
DE: "49",
IN: "91",
JP: "81",
};
export function normalizePhone(input, options = {}) {
if (typeof input !== "string") throw new TypeError("phone number must be a string");
const { defaultCountry = "US" } = options;
if (!Object.prototype.hasOwnProperty.call(DIAL_CODES, defaultCountry)) {
throw new RangeError(`unsupported default country "${defaultCountry}"`);
}
const dialCode = DIAL_CODES[defaultCountry];
const trimmed = input.trim();
if (trimmed === "") throw new Error("phone number is empty");
const hadPlus = trimmed.startsWith("+");
let digits = trimmed.replace(/\D/g, "");
if (!hadPlus && digits.startsWith("00")) {
digits = digits.slice(2);
} else if (!hadPlus) {
digits = digits.replace(/^0+/, "");
digits = `${dialCode}${digits}`;
}
if (digits.length < 8 || digits.length > 15) {
throw new RangeError("E.164 numbers contain 8 to 15 digits");
}
if (digits.startsWith("0")) throw new Error("E.164 national numbers cannot start with zero");
return `+${digits}`;
}
console.log(normalizePhone("(415) 555-0132"));
console.log(normalizePhone("+44 20 7946 0958"));
console.log(normalizePhone("0049 30 12345678"));
console.log(normalizePhone("0132 555 0199", { defaultCountry: "CN" }));