前言
在浏览器环境中,window 对象扮演着双重角色:它既是 JavaScript 访问浏览器窗口的接口,又是 ECMAScript 规定的 Global 对象。理解 window 的属性与方法,是掌握浏览器环境开发的第一步。
一、 Window 对象的双重身份
- 浏览器窗口接口:控制窗口大小、位置、导航等。
- 全局作用域:通过
var声明的变量、函数都会变成window的属性(注意:let和const不会)。
二、 窗口层级:Top 与 Parent 的奥秘
在处理 <iframe> 嵌套或多窗口场景时,精确定位窗口层级至关重要。
window.top:始终指向最外层的浏览器窗口(即最顶层的框架)。window.parent:指向当前窗口的直接上层窗口。如果当前窗口本身就是顶层,则parent等于self。window.self:指向当前窗口,与window等价。
同源限制:只有在同源(协议、域名、端口一致)的情况下,才能通过这些属性访问父窗口的 DOM 或变量。
三、 窗口尺寸:Inner vs Outer
很多开发者分不清这两组属性的区别,看图最直观:
| 属性 | 包含内容 | 备注 |
|---|---|---|
innerWidth / innerHeight | 仅页面视图区域(Viewport) | 不含工具栏、边框,包含滚动条 |
outerWidth / outerHeight | 整个浏览器窗口 | 包含地址栏、标签栏、侧边栏、窗口边框 |
提示:由于不同浏览器的 UI 组件(如侧边栏、收藏夹)占用空间不同,
outer系列的值在各平台差异较大。
四、 窗口导航与弹窗控制:window.open
window.open(url, name, features, replace) 是控制页面跳转的利器。
1. 参数细节
name:这是一个隐藏的“黑科技”。若已存在同名窗口,浏览器会在该窗口加载 URL,而不是新建标签页。这常用于单页面应用中的跨窗口通信。features:字符串格式,如"width=400,height=300,top=100,left=100"。replace:布尔值。如果为true,新页面将替换当前页在历史记录(History)中的位置,用户点击“后退”无法回到原页面。
2. 安全性与拦截处理
由于广告弹窗滥用,现代浏览器对 window.open 有严格限制:只有由用户操作(如点击事件)触发的弹窗才会被允许。
最佳实践检测代码:
// 尝试打开新窗口
let popup = window.open('https://juejin.cn', '_blank');
// 检测是否被拦截(某些插件会导致 popup 为 null,某些浏览器会抛出异常)
try {
if (popup == null || popup.closed || typeof popup.closed === 'undefined') {
console.warn('弹窗被浏览器拦截,请引导用户手动开启权限!');
}
} catch (e) {
console.error('弹窗被拦截或发生跨域错误');
}
六、 面试模拟题
Q1:window.onload 和 DOMContentLoaded 有什么区别?
参考回答:
DOMContentLoaded:当 HTML 文档被完全加载和解析完成时触发,不需要等待样式表、图像和子框架的完成加载。window.onload:等整个页面所有资源(包括图片、Flash、CSS等)全部加载完成后才触发。- 性能建议:通常建议将脚本逻辑放在
DOMContentLoaded中以提升响应速度。
Q2:如何通过 JS 判断当前页面是否在 iframe 中运行?
参考回答:
可以通过比较 window.self 和 window.top:
if (window.self !== window.top) {
console.log('当前页面运行在 iframe 中');
}
Q3:为什么不建议在全局作用域中使用变量名 name?
参考回答:
因为 window.name 是一个内置的特殊属性。它有一个特性:即使页面刷新或跳转到另一个域名,window.name 的值也会持久存在(直到窗口关闭)。如果你在全局定义了 var name = 'test',实际上是在修改这个内置属性,可能会引发意外的行为。