← 中文资源

简体中文版本

E.164 电话号码规范化

把本地与国际号码规范化为 E.164,处理国家区号、长途前缀与长度校验。

阅读英文原文

功能说明

该示例把用户输入的电话号码整理成 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" }));