用 JavaScript 获取网页域名看似简单,实际项目中却经常因为端口、相对路径、iframe 环境或者 Node.js 场景出现偏差。比如统计上报时只需要主机名,结果不小心传入了带端口的 host;又比如用 document.domain 判断当前域,可能因为页面脚本修改过而拿到错误值。本文把浏览器端和 Node 端获取域名的常用方法拆开说明,并封装一个可以直接复用的域名解析函数,覆盖从基础属性到注册域名提取的全流程。

一、location 对象的基础属性与端口陷阱
浏览器全局的 window.location 是获取当前页面地址信息的第一入口,但它身上的属性命名容易混淆。最常用的两个属性是 location.host 和 location.hostname。前者会带上端口号,后者只返回主机名,不包含端口。假设当前页面完整地址是 https://blog.ipipp.com:8443/path/list?page=1#section,各个属性的结果如下:
const loc = window.location; console.log(loc.href); // https://blog.ipipp.com:8443/path/list?page=1#section console.log(loc.host); // blog.ipipp.com:8443 console.log(loc.hostname); // blog.ipipp.com console.log(loc.origin); // https://blog.ipipp.com:8443 console.log(loc.protocol); // https: console.log(loc.pathname); // /path/list console.log(loc.port); // 8443
从结果可以看出,如果业务只需要域名本身,location.hostname 是更合适的选择,因为它天然忽略了端口。反过来,如果需要根据端口区分本地开发环境、测试环境和生产环境,则应该使用 location.host,它能保留 :8443 这样的端口信息。还有一个属性 location.origin 会返回协议加主机名加端口,适合作为接口请求的基础地址,但要注意它不会包含路径。
除了端口,还要留意 file:// 协议下的表现。当页面直接以本地文件方式打开时,部分浏览器中 location.hostname 可能返回空字符串,location.origin 也可能为 null。因此如果代码运行在本地文件环境,需要对空值做兜底处理,避免把空字符串写入统计参数或拼接到接口地址中。
二、使用 URL 构造函数统一解析域名
location 只能解析当前页面地址,无法直接处理一个自定义的 URL 字符串。现代浏览器和 Node.js 都内置了 URL 构造函数,可以统一解析完整地址和相对路径。它的用法是 new URL(input, base),其中 input 是要解析的地址,base 是可选的基础地址。下面的例子展示了如何从完整地址中取出不包含端口的域名:
const url = new URL('https://user:pass@blog.ipipp.com:8080/search?q=js#top');
console.log(url.hostname); // blog.ipipp.com
console.log(url.host); // blog.ipipp.com:8080
console.log(url.port); // 8080
console.log(url.protocol); // https:
console.log(url.searchParams.get('q')); // js
如果需要解析相对路径,必须传入 base 参数,否则 URL 会抛出类型错误。例如页面位于 https://ipipp.com/,要解析 /docs/js 这个路径,可以写 new URL('/docs/js', 'https://ipipp.com/'),最终得到的 hostname 就是 ipipp.com。这种写法在 Node.js 脚本、Web Worker 和 Service Worker 中同样可用,因为这些环境不一定有 window.location。
相比之下,使用 <a> 元素也能解析地址,做法是动态创建一个 <a> 节点并设置 href,然后读取 hostname。不过这种方式依赖 DOM,且代码量更多,不如 URL 直观。除非需要兼容非常老旧的浏览器,否则统一使用 URL 是更清晰的方案。
三、document.domain 的边界与限制
document.domain 在早期前端开发中常被用来实现子域名之间的跨域通信,例如把 blog.ipipp.com 的页面通过设置 document.domain = 'ipipp.com' 来与主站共享 Cookie 或操作父窗口。但它并不是一个可靠的域名获取来源。它首先返回的是当前文档的域名,但这个值可以被脚本主动修改,一旦修改后就无法再改回原来的子域名,而且现代浏览器对它的限制越来越严格。
// 当前页面地址为 https://blog.ipipp.com/article/1
console.log(document.domain); // blog.ipipp.com
try {
document.domain = 'ipipp.com';
console.log(document.domain); // ipipp.com
} catch (e) {
console.error('设置失败', e);
}
从上面的代码可以看出,document.domain 会从 blog.ipipp.com 变成 ipipp.com。如果后续代码拿它来判断当前页面所在域,就可能拿到不准确的值。在 iframe 场景中尤其明显,因为 iframe 内的文档可能有独立的 document.domain,而且沙箱 iframe 通常禁止修改该属性。
因此,精确获取网页域名时应当优先使用 location.hostname 或者基于 URL 解析 location.href 得到的 hostname。如果确实需要判断两个页面是否同源,也不要只比较 document.domain,而应综合协议、端口和主机名三个部分。
四、封装一个健壮的域名获取函数并实战
在项目里重复写域名解析代码容易产生风格不一致的问题,建议封装成工具函数。下面这个函数优先解析传入的 URL,未传时自动读取当前页面的 location.hostname,同时兼容 Node.js 环境和浏览器环境:
function getHostname(input) {
if (input) {
return new URL(input).hostname;
}
if (typeof location !== 'undefined') {
return location.hostname;
}
throw new Error('当前环境没有 location,且未传入 URL');
}
// 使用示例
console.log(getHostname()); // 当前页面域名,例如 blog.ipipp.com
console.log(getHostname('https://api.ipipp.com/v1/user')); // api.ipipp.com
如果业务需要从完整主机名中提取注册域名,例如将 www.ipipp.com 转换为 ipipp.com,可以搭配一个简化版的后缀处理函数。需要注意 com.cn、co.uk 这类二级后缀,不能简单用最后两段拼接:
function getRootDomain(hostname) {
const parts = hostname.split('.');
const twoLevelTlds = new Set(['com.cn', 'net.cn', 'org.cn', 'gov.cn', 'co.uk', 'com.au']);
if (parts.length >= 3) {
const lastTwo = parts.slice(-2).join('.');
if (twoLevelTlds.has(lastTwo)) {
return parts.slice(-3).join('.');
}
return parts.slice(-2).join('.');
}
return hostname;
}
console.log(getRootDomain('www.ipipp.com')); // ipipp.com
console.log(getRootDomain('news.city.ipipp.com.cn')); // ipipp.com.cn
这个简化版本只覆盖常见后缀,生产环境如果涉及全球域名后缀,建议引入公共后缀列表库来保证准确性。对于一般的中小型项目,上述逻辑已经可以覆盖大多数业务域名。
在 Node.js 中测试时,只需要安装 Node.js 后直接使用全局的 URL,不需要额外安装 npm 包。把代码保存为 domain.js,在命令行执行 node domain.js 即可查看输出。这样浏览器端和 Node 端可以共用同一套域名解析函数,减少环境差异带来的重复调试。
总的来说,获取网页域名最推荐的方式是:当前页面用 location.hostname,解析任意 URL 用 new URL(input).hostname,需要注册域名时再基于后缀规则处理。避开 document.domain 的动态修改影响,也避免直接截取字符串造成的边界错误,就能在不同项目中稳定获得准确的域名信息。
获取网页域名JavaScriptURL API修改时间:2026-09-30 07:04:25