在JavaScript中,准确获取当前域名及子域名信息,核心是使用window.location对象的几个属性,其中window.location.hostname是获取纯域名部分最直接的方法。
先分清location对象的三个关键属性
很多人一上来就用window.location.host,结果把端口号也带出来了,要准确区分,先看下表:
| 属性 | 返回值示例 | 说明 |
|---|---|---|
window.location.hostname |
www.example.com |
只返回域名部分,不含端口和协议 |
window.location.host |
www.example.com:8080 |
包含域名和端口号(如果端口非默认) |
window.location.origin |
https://www.example.com:8080 |
协议+域名+端口,不含路径 |
如果仅需要当前域名,优先用hostname,它已经过滤掉http://和路径,也不会带上端口,只有当你需要区分HTTP/HTTPS或处理非标准端口时,才考虑结合location.protocol和location.port。
当前域名与子域名信息怎么准确拆分?
拿到hostname只是第一步,实际项目里经常需要区分主域名和子域名,比如news.baidu.com里,baidu.com是主域名,news是一级子域名,要准确拆分,不能简单用split('.')然后取倒数两个部分,因为有些域名是双后缀,比如example.com.cn,主域名其实是example.com.cn。
维护一个公共后缀列表
最稳妥的方式是维护一个常见公共后缀数组,比如.com.cn、.net.cn、.org.cn、.co.uk、.com.au等,业内专家指出,公共后缀列表(Public Suffix List)是处理这类问题的行业共识基础,但前端自己维护一个简化版就够用。
实操思路:
const hostname = window.location.hostname; // a.b.example.com.cn
const parts = hostname.split('.');
// 判断最后两段是否属于双后缀组合
const doubleSuffix = ['com.cn', 'net.cn', 'org.cn', 'co.uk', 'com.au', 'gov.cn'];
const lastTwo = parts.slice(-2).join('.');
let mainDomain, subDomain;
if (doubleSuffix.includes(lastTwo)) {
// 主域名最后三段
mainDomain = parts.slice(-3).join('.');
// 子域名是剩余部分
subDomain = parts.slice(0, -3).join('.');
} else {
mainDomain = parts.slice(-2).join('.');
subDomain = parts.slice(0, -2).join('.');
}
上述代码能覆盖大多数情况,如果hostname本身就是主域名,比如直接访问example.com,那么subDomain会变成空字符串,处理逻辑时需要判空。

针对多级子域名的通用解法
如果存在多级子域名,比如a.b.example.com,你需要的是完整的子域名前缀a.b还是最靠近主域名的b?需求决定逻辑。
- 想拿完整子域链:
parts.slice(0, -2).join('.')(针对普通单后缀域名) - 想拿最近一级子域:
parts[parts.length - 3] - 想拿主域名本身:
parts.slice(-2).join('.')(普通情况)
如果你的场景是设置cookie,一条经验法则:cookie写入主域名,而不是子域名,这样所有子域名都能共享登录状态,比如document.cookie = "token=xxx; domain=.example.com; path=/",注意domain前面加个点。
js获取当前域名时端口信息怎么处理?
有时候接口需要动态拼接,比如开发环境端口是8080,生产环境是默认443,单纯用hostname会丢端口,这时要看具体场景:
需要完整域名且带端口
const fullDomain = window.location.host; // 包含端口(非默认端口时)
location.host的值在端口为80(HTTP)或443(HTTPS)时不会显示端口号,浏览器会自动省略,这正好符合大多数业务需求。
只获取端口
const port = window.location.port;
如果返回为空字符串,说明使用的是默认端口,不要把空字符串当成“没有端口”,它在拼接URL时会有坑。
协议也要带上时
const origin = window.location.origin;
注意origin在较老浏览器(IE10及以下)里不受支持,如果要兼容,手动拼接:
const origin = window.location.protocol + '//' + window.location.host;
单页面应用与iframe场景下如何获取真实域名?
SPA路由不会改变location.hostname,所以常规操作没问题,但如果你嵌在iframe里,情况就变了。
同源iframe与跨域iframe
- 同源iframe:
window.location.hostname和parent.location.hostname都能拿到各自文档的真实域名。 - 跨域iframe:访问
parent.location.hostname会抛SecurityError,处理方式要么用postMessage与父页面通信,要么在父页面把域名信息通过URL参数传进来。
行业共识认为,跨域环境下最可靠的方式是让父页面显式传递域名参数,而不是前端强行探测。
// 父页面拼接iframe src iframe.src = 'https://app.example.com?parentDomain=' + encodeURIComponent(window.location.hostname);
子页面读取URLSearchParams即可。
代理环境下hostname可能不是真实域名

如果后端做了反向代理,window.location.hostname返回的是浏览器地址栏里的域名,不是服务器内部域名,这通常没问题,因为前端本来就需要用户可见的域名。
但如果涉及CORS、cookie跨域写入,就要去检查后端收到的Host头是否和前端一致,多数情况下,前端拿到的一定是用户实际访问的域名,这点不用怀疑。
操作路径:写一个完整的域名解析工具函数
把上面要点整合,封装成可直接使用的函数,这个函数能返回:主域名、完整子域前缀、当前hostname、协议、端口。
function getDomainInfo() {
const hostname = window.location.hostname || '';
const protocol = window.location.protocol;
const port = window.location.port;
const parts = hostname.split('.');
const doubleSuffix = ['com.cn','net.cn','org.cn','gov.cn','co.uk','com.au','co.jp'];
let mainDomain = '';
let subPrefix = '';
if (parts.length >= 2) {
const lastTwo = parts.slice(-2).join('.');
if (doubleSuffix.includes(lastTwo) && parts.length >= 3) {
mainDomain = parts.slice(-3).join('.');
subPrefix = parts.slice(0, -3).join('.');
} else {
mainDomain = parts.slice(-2).join('.');
subPrefix = parts.slice(0, -2).join('.');
}
} else {
mainDomain = hostname; // 本地环境如 localhost
}
return {
hostname,
protocol,
port,
mainDomain,
subDomain: subPrefix,
origin: protocol + '//' + hostname + (port ? ':' + port : '')
};
}
使用示例:
const info = getDomainInfo(); console.log(info.mainDomain); // baidu.com console.log(info.subDomain); // www
本地开发时localhost也会被这个函数处理为mainDomain = localhost,子域名为空,不会报错。
场景实战:js 获取当前域名后常用业务处理
动态切换API地址
前后端部署在不同子域时,前端需要根据当前域名判断API基地址。
const envMap = {
'dev.example.com': 'https://api-dev.example.com',
'test.example.com': 'https://api-test.example.com',
'www.example.com': 'https://api.example.com'
};
const apiBase = envMap[window.location.hostname] || envMap['www.example.com'];
多域名CDN资源白名单
安全检测场景下,你要判断当前页面是否来自合法域名,把hostname与白名单数组比对,注意完全匹配而不是子串匹配:
const allowedDomains = ['www.example.com', 'm.example.com'];
if (!allowedDomains.includes(window.location.hostname)) {
// 非白名单域名,执行拦截逻辑
}

百度小程序或移动端适配
在百度智能小程序或移动端H5中,获取当前域名方式同样是window.location.hostname,但要注意小程序环境下部分API限制,建议通过location.href解析,直接使用new URL(window.location.href)也可以拿到hostname,这个方法在支持ES6的环境下都没问题。
常见坑与边界情况
IP地址与localhost
直接访问http://192.168.1.10:3000时,hostname是168.1.10,split('.')后长度是4,上面的函数会误判mainDomain为10,需要额外处理:
if (/^d+.d+.d+.d+$/.test(hostname)) {
mainDomain = hostname;
subPrefix = '';
}
同样,localhost要单独跳过公共后缀逻辑。
域名大小写
window.location.hostname返回的通常是小写,但某些浏览器可能保留原始大小写,建议统一toLowerCase()再比较。
端口导致的坑
如果测试环境端口不是80/443,用location.host做域名判断时会把端口带进判断逻辑,导致白名单失效,建议判断域名时永远使用hostname,涉及拼接URL时再用host。
相关问题解答
js 获取当前域名和子域名信息时,为什么不能用document.domain代替?
document.domain是旧方案,它原本用于跨子域访问iframe,现在浏览器对document.domain的写入限制越来越严格,且它在多个标签页或同源策略下行为不一致,跨域通信首选postMessage,不要依赖修改document.domain来获取域名。
只获取主域名不带子域名,最简单的方法是什么?
如果确认网站只使用单后缀域名(如.com、.net),直接window.location.hostname.split('.').slice(-2).join('.')即可,如果存在双后缀,务必参考上面的公共后缀列表判断,多数情况下可以用正则辅助,但列表判断最稳妥。
微信内置浏览器里js获取当前域名有兼容性问题吗?
没有。window.location.hostname在微信内置浏览器、各类APP webview中都遵循标准实现,唯一要注意的是,如果webview启用了自定义URL scheme,比如wx://somepage,这时hostname可能返回空,遇到这种情况,改用window.location.href去解析,或者让原生端通过注入参数传递域名。
获取域名这件事本身不难,难点在于各种边界场景,用一个封装好的函数统一处理,比每次手写逻辑更可靠,记住核心结论:取纯域名用hostname,取带端口用host,分离子域名时要小心双后缀。