js匹配域名怎么做,js正则匹配域名方法
- 运维技术
- 2026-08-26
- 3
在JavaScript中匹配域名,核心方案是使用window.location对象获取当前页面URL,再通过hostname、host或origin属性提取域名部分,最后用正则表达式、字符串方法或数组遍历完成精确匹配与逻辑判断。
前端开发中,域名匹配是路由鉴权、环境切换、埋点统计和防截持的常见前置步骤,很多开发者习惯用indexOf一把梭,但在多环境、多子域名的复杂场景下,这种写法容易埋雷,本文从实际业务出发,把域名匹配的常用姿势、坑点以及性能考量一次说清。
js获取当前域名:三种属性别再混用
浏览器提供的window.location对象里,有多个属性都能拿到地址信息,但用途完全不同,用错了,轻则判断失效,重则跨域报错。
hostname、host、origin的差异
- window.location.hostname:只返回域名部分,不含端口号,例如https://shop.example.com:8080/path,它返回shop.example.com。
- window.location.host:返回域名加端口号,上例返回shop.example.com:8080。
- window.location.origin:返回协议、域名和端口号的完整组合,上例返回https://shop.example.com:8080。
判断域名归属时,优先使用hostname,因为端口号变化会导致host匹配失败,而origin包含协议,如果站点同时支持HTTP和HTTPS,直接比对origin会得到不一致的结果。
// 推荐:只拿纯域名 const currentDomain = window.location.hostname; // 不推荐:包含了端口,匹配时容易踩坑 const withPort = window.location.host; // 特殊场景:需要判断协议+域名时再用 const fullOrigin = window.location.origin;
兼容性提醒:IE时代的遗留问题
window.location.origin在IE 10及以下版本中不存在,虽然这类浏览器已基本退出市场,但如果你的产品仍需要兼容老旧内核(如某些政务系统内嵌浏览器),建议自行拼接:
const origin = window.location.origin || (window.location.protocol + '//' + window.location.hostname);
js判断域名跳转:多环境下的分流策略
日常开发中,最常见的需求是区分本地开发环境、测试环境和生产环境,并执行不同的逻辑或跳转。
本地开发环境的域名识别
本地开发时,域名通常是localhost或0.0.1,有时还会带端口号,判断时可以这样写:
const host = window.location.hostname; // 判断是否为本地环境 if (host === 'localhost' || host === '127.0.0.1') { // 加载mock数据或使用代理 console.log('当前为本地开发环境'); }
但有些团队的本地环境使用dev.example.com这类自定义域名,这时候写死就不够用了,需要维护一个环境白名单数组。
生产环境的域名白名单校验
当页面可能被第三方站点通过iframe嵌入时,为了防止恶意盗链,需要校验当前域名是否在允许列表内:
const allowedDomains = ['www.example.com', 'm.example.com', 'admin.example.com']; const currentDomain = window.location.hostname; if (allowedDomains.indexOf(currentDomain) === -1) { // 跳转到错误页或执行阻止逻辑 window.location.href = 'https://www.example.com/error'; }
行业共识认为,这种白名单校验配合后端接口的Referer检查,能有效降低跨站数据泄露风险。
场景实操:A/B测试中的域名分流
做A/B实验时,有时需要让特定流量访问不同的域名,常见的做法是维护一个映射对象:
const envMap = { 'test.example.com': 'https://beta.example.com', 'pre.example.com': 'https://release.example.com' }; const target = envMap[window.location.hostname]; if (target) { window.location.replace(target); }
用replace而不是href赋值,可以避免在历史记录中留下中间页,用户按返回键时不会回到跳转前的页面。
js匹配多个域名:数组遍历与正则表达式的取舍
业务场景中,往往要判断当前域名是否属于一组域名中的任意一个,或者是否包含某个关键词。
用includes判断域名是否包含某字符串
如果只是想判断域名是否包含特定关键词(比如所有子域名都带example),直接用字符串方法即可:
const host = window.location.hostname; // 判断是否包含 example if (host.includes('example')) { console.log('当前域名属于 example 体系'); }
但includes有个隐患:它会匹配到不该匹配的域名,例如notexample.com也包含example。如果做精确匹配,不要用includes。
精确匹配多个域名的高效写法
需要精确匹配多个域名时,用数组的includes方法更直观:
const allowedDomains = ['www.example.com', 'm.example.com', 'api.example.com']; const currentDomain = window.location.hostname; if (allowedDomains.includes(currentDomain)) { // 执行对应逻辑 }
这是ES6语法,兼容性良好,代码可读性也高,如果项目需要兼容极老浏览器,用indexOf替代:
if (allowedDomains.indexOf(currentDomain) > -1) { // 逻辑同上 }
子域名匹配:后缀判断的边界问题
还有一种常见需求:匹配所有以example.com结尾的子域名,包括a.example.com和b.example.com,但不包括fakeexample.com,这时用endsWith加边界检查:
const host = window.location.hostname; const suffix = '.example.com'; // 必须是子域名或主域名本身 if (host === 'example.com' || host.endsWith(suffix)) { console.log('匹配 example.com 及其子域名'); }
注意边界:如果直接写host.endsWith('example.com'),fakeexample.com也会被命中。加上点号前缀.example.com能有效避免这类误判。
正则表达式的适用场景
当匹配规则复杂(例如要求域名以shop开头且以.com,正则表达式更灵活:
const pattern = /^shop...com$/; if (pattern.test(window.location.hostname)) { console.log('匹配 shop 子域名'); }
正则性能略低于字符串方法,但在单次页面加载中差异可忽略,维护成本方面,正则更依赖注释说明,团队协作时建议在代码旁写清意图。
js获取当前域名后做参数携带与埋点
拿到域名后,通常还要配合路径、查询参数一起使用,才能完成完整的数据上报或逻辑分支。
拼接完整URL做埋点上报
埋点场景下,需要把当前页面的完整地址发给统计服务器,这时只用hostname不够,需要拼接路径和参数:
const fullPath = window.location.pathname; const queryString = window.location.search; const reportUrl = window.location.hostname + fullPath + queryString; // 发送到埋点服务 navigator.sendBeacon('https://track.example.com/collect', reportUrl);
navigator.sendBeacon比XMLHttpRequest更适合页面卸载时的数据发送,不会中断请求。
结合hash路由的域名判断
单页应用常使用hash路由,此时window.location.hash保存了路由信息,判断域名后再取hash值,可以定位到具体页面:
const host = window.location.hostname; const hashRoute = window.location.hash; if (host === 'm.example.com' && hashRoute.startsWith('#/product/')) { // 移动端商品详情页逻辑 }
域名匹配的性能与安全注意事项
很多开发者只关注功能是否跑通,忽略了匹配逻辑本身的健壮性,这里有两个高频问题值得注意。
频繁操作DOM导致的性能损耗
有些代码在每次滚动或resize事件里都去读取window.location,这本身开销不大,但如果在回调里触发了重排或重绘,性能就会明显下降,建议把域名缓存到变量中:
// 页面加载时缓存 const cachedHost = window.location.hostname; // 事件回调中使用缓存变量 window.addEventListener('resize', () => { // 直接使用 cachedHost,不重复读取 });
防止域名截持的代码层面建议
域名截持通常发生在DNS层面或代理层面,前端代码能做的有限,但可以增加基础校验:
// 检测页面是否被iframe嵌入,且父页面域名不一致 try { if (window.top.location.hostname !== window.location.hostname) { // 弹窗提示或执行自我保护逻辑 console.warn('页面被嵌入到其他域名下'); } } catch (e) { // 跨域限制时,说明被嵌入了 console.warn('无法访问父页面域名,可能存在跨域嵌入'); }
这段代码利用了跨域访问会抛异常的特性,是前端防点击截持的常见手法,需要注意的是,它不能替代后端安全策略,只是增加了一层客户端检测。
常见问题速查
Q1:js获取当前域名时,为什么有时返回localhost而不是实际IP?
因为window.location.hostname返回的是浏览器地址栏中显示的内容,如果你通过http://192.168.1.10:8080访问,它返回168.1.10;通过http://localhost:8080访问,就返回localhost,两者都代表本机,但字符串不同,判断时需同时处理,更稳妥的做法是检查hostname是否为localhost、0.0.1或:1(IPv6本地地址)。
Q2:js匹配多个域名时,大小写问题怎么处理?
域名本身不区分大小写,但浏览器返回的hostname通常是小写。为了保险起见,建议统一转小写再比较,尤其是从window.location.href手动解析域名时,可能保留原始大小写。
const host = window.location.hostname.toLowerCase();
Q3:本地文件(file://协议)打开页面时,location.hostname返回什么?
返回空字符串,因为file://协议下没有域名概念,如果你用本地文件测试涉及域名的代码,需要起一个本地服务(如npx serve)来模拟HTTP环境,否则判断逻辑会走空字符串分支,据统计,相当一部分前端初学者在本地直接双击HTML文件调试时,会遇到这类域名判断失效的问题。
域名匹配本身不难,难在边界情况的处理和团队规范的统一,把hostname作为默认选择,用精确匹配代替模糊匹配,对多环境场景维护一份清晰的域名清单,大部分需求都能稳妥覆盖,代码是给人读的,匹配逻辑写清楚,后续维护的人会感谢你。