前言
在前端开发中,无论是获取 URL 参数、实现页面跳转,还是处理锚点定位,都离不开 location 对象。它既是 window 的属性,也是 document 的属性,是连接用户与网页地址的核心纽带。
一、 URL 的解构艺术
location 对象将复杂的 URL 拆解为多个易于操作的属性。以下是以 https://example.com:8080/path/index.html?q=js#section1 为例的解析:
| 属性 | 描述 | 示例值 |
|---|---|---|
href | 整个完整 URL | https://example.com:8080/... |
protocol | 协议(带冒号) | https: |
hostname | 域名(不带端口) | example.com |
port | 端口号 | 8080 |
host | 域名 + 端口 | example.com:8080 |
pathname | 路径部分 | /path/index.html |
search | 查询参数(带 ?) | ?q=js |
hash | 锚点(带 #) | #section1 |
origin | 源(协议+域名+端口) | https://example.com:8080 |
二、 页面跳转与历史记录
修改 location 的属性是触发页面跳转的最直接方式。但不同的操作对历史记录History Stack的影响截然不同。
1. 修改属性触发跳转
除了 hash 之外,修改任何属性都会导致页面重新加载。
location.href = '...'(最常用)location.hostname = '...'location.search = '?id=123'
2. 方法对比:assign vs replace
-
location.assign(url)- 行为:加载新页面,并将当前页面保存到历史记录中。
- 效果:用户点击“后退”按钮,可以回到跳转前的页面。
-
location.replace(url)- 行为:用新 URL 替换当前页面的历史记录条目。
- 效果:用户点击“后退”无法回到跳转前的页面。
- 场景:适用于登录重定向、表单提交后的跳转,防止用户重复提交。
三、 页面刷新:reload()
location.reload() 用于重新加载当前文档。
- 普通刷新:
location.reload(),浏览器可能会从缓存中读取资源。 - 强制刷新:虽然在旧版文档中提到传
true可强制从服务器下载,但 注意: 在最新的 W3C 标准中,reload()不再接受参数。现代浏览器倾向于通过控制Cache-Control请求头来决定是否跳过缓存。
四、 实战技巧:如何优雅地解析 Search 参数?
以前我们通过复杂的正则或 split('?') 来解析 URL 参数,现在推荐使用原生 API:
// 假设当前 URL 为 ?name=juejin&id=100
const urlParams = new URLSearchParams(window.location.search);
console.log(urlParams.get('name')); // "juejin"
console.log(urlParams.has('id')); // true
五、 面试模拟题
Q1:location.href 和 location.replace 有什么区别?
参考回答:
location.href 本质上是调用了 location.assign(),它会在浏览器历史记录中新增一条记录,用户可以后退。而 location.replace() 会替换当前的历史条目,后退按钮将失效。这在处理敏感业务逻辑(如支付完成页、登录后跳转)时非常有用。
Q2:如何只改变 URL 却不触发页面刷新?
参考回答:
- 修改
location.hash:改变锚点不会导致页面重载,只会触发hashchange事件(这是早期单页面应用 SPA 路由的实现原理)。 - 使用 History API:调用
history.pushState()或history.replaceState()。它们可以修改路径和参数,但完全不会触发页面刷新,是现代前端框架(Vue Router/React Router)的核心。
Q3:location.host 和 location.hostname 的区别是什么?
参考回答:
hostname只包含域名部分(如juejin.cn)。host包含域名和端口号(如juejin.cn:443)。如果当前是默认端口(80 或 443),则两者返回值相同。