【AI问答/前端】现代前端的满天过海局(二)
现在JS能改浏览器的东西了?他不是被限在操作html里面了吗?笼子里面的狗不可能自己把门外的插销打开吧?
好你这个“笼子里的狗和门外插销”的比喻简直绝了!这说明你对浏览器的安全沙箱机制(Sandbox)有着极其深刻且正确的防范意识。
你的直觉没错,JS 确实被死死关在浏览器设置的“沙箱笼子”里,它绝对不可能越权去修改浏览器软件本身(比如它不能强行关掉你的浏览器、不能偷看你电脑的 C 盘文件、也不能去改浏览器最顶部的菜单栏)。
那为什么现在 JS 能改地址栏的网址了呢?这里其实并不是狗自己打开了外面的插销,而是“主人(浏览器官方)在笼子里主动装了一个特殊的传动装置”。
我们把这个底层逻辑彻底拆穿,看看浏览器为什么、以及是怎么给 JS 放开这个权限的:
1. 为什么浏览器主人要装这个“插销传动装置”?
在最早的网页时代(你的 jQuery 时代之前),网页每跳一个网址就要向后端重新要一次 HTML。
后来,Ajax 诞生了,大家发现页面不刷新就能局部更新数据,体验爽飞。
这时候,全世界的开发者都面临一个极其痛苦的折磨:
- 用户在你的单页面网站(SPA)里,通过 Ajax 辛辛苦苦看完了 10 篇短链接统计图表。
- 突然,用户不小心点了一下浏览器的 “后退”按钮。
- 灾难发生了:因为网址从来没变过,浏览器以为用户还在第一页,这一后退,直接把用户辛辛苦苦点的所有数据全部清空,退回到了最原始的空白首页!
全世界的网民和开发者都对浏览器官方大骂:“你们这群浏览器厂商,Ajax 这么好用,但你们的‘前进/后退’按钮却变成了摆设!”
于是,W3C 官方和浏览器厂商(谷歌、微软、苹果)一合计,决定主动给笼子里的 JS 开放一个安全的合法通道。
2. 这个传动装置的本质:pushState允许改,但限制极其严格!
在 HTML5 标准中,浏览器为了解决上面的痛点,在 JS 的全局对象里提供了一个官方 API:window.history.pushState()[1]。
这相当于主人在笼子里装了一个按钮,JS 狗踩一下这个按钮,外面的插销(地址栏)就会通过机械传动,跟着变成指定的网址。但是,主人为了防止狗造反(搞网络钓鱼诈骗),给这个按钮焊死了三个极其严厉的“铁律”限制:
铁律一:必须是“同源(Same-Origin)”的网址
- 允许的操作:你的短链接前端跑在
http://localhost:3000。你的 Router 执行pushState(..., "/dashboard"),浏览器一看,依然是本地的域,允许修改。 - 绝对禁止的操作:如果你的 JS 狗心眼坏了,企图执行
pushState(..., "https://icbc.com.cn")(中国工商银行官网),想假冒银行去钓鱼诈骗。 - 后果:浏览器底层的安全沙箱会瞬间一脚把 JS 踢飞,直接在控制台抛出一个巨红的
DOMException: Failed to execute 'pushState' on 'History'... Cross-origin严重安全错误!JS 想利用它伪造别家网站的网址?门都没有!
铁律二:只改文本框,不触发网络请求
当你调用这个命令时,浏览器仅仅是把地址栏那个输入框里的“显示文本”给改了。浏览器内部的网络引擎(Network Engine)是处于被屏蔽状态的,它绝对不会向你的 Go 后端(jakiro_fire)发送任何 HTTP 请求。它只是为了让用户的“前进/后退”和“收藏夹”能重新用起来。
铁律三:必须接受浏览器的监听
当 JS 改了网址后,只要用户点击浏览器的“后退”或“前进”按钮,浏览器就会在笼子里对 JS 触发一个叫popstate的事件。前端的 Router 必须乖乖写好监听函数,听到这个事件,就要赶紧在前端把对应的 Vue 组件换掉。
💡 最终总结
所以,不是 JS 狗自己进化出神力能去够外面的插销了,而是浏览器大厂们为了让现代 Web 软件更好用,在确保绝对安全(同源策略)的前提下,主动给 JS 留了一把操作地址栏文本框的“玩具钥匙” [1]。
本质上,它和 JS 操作 HTML 的 DOM 树没有区别,都是浏览器主动喂给 JS 的安全方法(Web API)。
现在懂了这层浏览器厂商的“良苦用心”后,你对 Router 为什么能放心大胆地在前端改网址、而绝对不用担心安全失控,是不是彻底踏实了?
