- Global 作用域
- window 对象的属性
- window 对象的方法
- 全局对象属性 详解
document
- Cookie
- URL
BOM 的核心是 window 对象,表示浏览器的实例。 window 对象在浏览器中有两重身份,一个是 ECMAScript中的 Global 对象,另一个就是浏览器窗口的JavaScript API接口,里面包含了当前客户端浏览器的一些信息,和常用的一些浏览器操作。这意味着网页中定义的所有对 象、变量和函数都以 window 作为其 Global 对象,都可以访问其上定义的 parseInt() 等全局方 法。
浏览器里面,window对象(注意,w为小写)指当前的浏览器窗口。它也是当前页面的顶层对象,即最高一层的对象,所有其他对象都是它的下属。一个变量如果未声明,那么默认就是顶层对象的属性。
Global 作用域
因为 window 对象被复用为ECMAScript的 Global 对象,所以通过 var 声明的所有全局变量和函 数都会变成 window 对象的属性和方法。
var age = 29;
var sayAge = () => alert(this.age);
alert(window.age); // 29
sayAge(); // 29
window.sayAge(); // 29
这里,变量 age 和函数 sayAge() 被定义在全局作用域中,它们自动成为了 window 对象的成 员。因此,变量 age 可以通过 window.age 来访问,而函数 sayAge() 也可以通过 window.sayAge() 来访问。因为 sayAge() 存在于全局作用域, this.age 映射到 window.age ,所以就可以显示正确的结果了。 如果在这里使用 let 或 const 替代 var ,则不会把变量添加给全局对象。
window 对象的属性
window.name
window.name属性是一个字符串,表示当前浏览器窗口的名字。窗口不一定需要名字,这个属性主要配合超链接和表单的target属性使用。
window.name = 'Hello World!';
console.log(window.name)
// "Hello World!"
该属性只能保存字符串,如果写入的值不是字符串,会自动转成字符串。各个浏览器对这个值的储存容量有所不同,但是一般来说,可以高达几MB。
只要浏览器窗口不关闭,这个属性是不会消失的。举例来说,访问a.com时,该页面的脚本设置了window.name,接下来在同一个窗口里面载入了b.com,新页面的脚本可以读到上一个网页设置的window.name。页面刷新也是这种情况。一旦浏览器窗口关闭后,该属性保存的值就会消失,因为这时窗口已经不存在了。
window.closed window.opener
window.closed 属性返回一个布尔值,表示窗口是否关闭。
window.closed // false
上面代码检查当前窗口是否关闭。这种检查意义不大,因为只要能运行代码,当前窗口肯定没有关闭。这个属性一般用来检查,使用脚本打开的新窗口是否关闭。
var popup = window.open();
if ((popup !== null) && !popup.closed) {
// 窗口仍然打开着
}
window.opener属性表示打开当前窗口的父窗口。如果当前窗口没有父窗口(即直接在地址栏输入打开),则返回null。
window.open().opener === window // true
上面表达式会打开一个新窗口,然后返回true。
如果两个窗口之间不需要通信,建议将子窗口的opener属性显式设为null,这样可以减少一些安全隐患。
var newWin = window.open('example.html', 'newWindow', 'height=400,width=400');
newWin.opener = null;
上面代码中,子窗口的opener属性设为null,两个窗口之间就没办法再联系了。
通过opener属性,可以获得父窗口的全局属性和方法,但只限于两个窗口同源的情况,且其中一个窗口由另一个打开。元素添加rel=”noopener”属性,可以防止新打开的窗口获取父窗口,减轻被恶意网站修改父窗口 URL 的风险。
<a href="https://an.evil.site" target="_blank" rel="noopener">
恶意网站
</a>
窗口本身 window.self window.window
window.self和window.window属性都指向窗口本身。这两个属性只读。
window.self === window // true
window.window === window // true
框架窗口 window.frames,window.length
window.frames属性返回一个类似数组的对象,成员为页面内所有框架窗口,包括frame元素和iframe元素。window.frames[0]表示页面中第一个框架窗口。
如果iframe元素设置了id或name属性,那么就可以用属性值,引用这个iframe窗口。比如
frames属性实际上是window对象的别名。
frames === window // true
因此,frames[0]也可以用window[0]表示。但是,从语义上看,frames更清晰,而且考虑到window还是全局对象,因此推荐表示多窗口时,总是使用frames[0]的写法。
window.length属性返回当前网页包含的框架总数。如果当前网页不包含frame和iframe元素,那么window.length就返回0。
window.frames.length === window.length // true
上面代码表示,window.frames.length与window.length应该是相等的。
window.frameElement 当前窗口所在的那个元素节点
window.frameElement属性主要用于当前窗口嵌在另一个网页的情况(嵌入
// HTML 代码如下
// <iframe src="about.html"></iframe>
// 下面的脚本在 about.html 里面
var frameEl = window.frameElement;
if (frameEl) {
frameEl.src = 'other.html';
}
上面代码中,frameEl变量就是
窗口关系 window.top,window.parent
window.top 对象始终指向最上层(最外层)窗口,即浏览器窗口本身。主要用于在框架窗口(frame)里面获取顶层窗口。
而 window.parent 对象则始终指向当前窗 口的父窗口。如果当前窗口是最上层窗口,则 parent 等于 top (都等于 window 相当于指向自身)。最上层的 window 如果不是通过 window.open() 打开的,那么其 name 属性就不会包含值。
if (window.parent !== window.top) {
// 表明当前窗口嵌入不止一层
}
window.status 浏览器状态栏的文本
window.status属性用于读写浏览器状态栏的文本。但是,现在很多浏览器都不允许改写状态栏文本,所以使用这个方法不一定有效。
window.devicePixelRatio
window.devicePixelRatio属性返回一个数值,表示一个 CSS 像素的大小与一个物理像素的大小之间的比率。也就是说,它表示一个 CSS 像素由多少个物理像素组成。它可以用于判断用户的显示环境,如果这个比率较大,就表示用户正在使用高清屏幕,因此可以显示较大像素的图片。
窗口大小属性
window.innerHeight,window.innerWidth
window.innerHeight和window.innerWidth属性,返回网页在当前窗口中可见部分的高度和宽度,即“视口”(viewport)的大小(单位像素)。这两个属性只读。
用户放大网页的时候(比如将网页从100%的大小放大为200%),这两个属性会变小。因为这时网页的像素大小不变(比如宽度还是960像素),只是每个像素占据的屏幕空间变大了,因此可见部分(视口)就变小了。
注意,这两个属性值包括滚动条的高度和宽度。
也可以通过document.documentElement.clientWidth、document.body.clientWidth 和 document.documentElement.clientHeight、document.body.clientHeight 返回页面视口的宽度和高度。
window.outerHeight,window.outerWidth
window.outerHeight和window.outerWidth属性返回浏览器窗口的高度和宽度,包括浏览器菜单和边框(单位像素)。这两个属性只读。
window.innerWidth // 显示区域宽度
window.innerHeight // 显示区域高度
window.outerWidth // 整浏览器宽度
window.outerHeight // 整浏览器高度
窗口位置属性
浏览器窗口尺寸通常无法满足完整显示整个页面,为此用户可以通过滚动在有限的视口中查看文档。 度量文档相对于视口滚动距离的属性有两对,返回相等的值: window.pageXoffset / window.scrollX 和 window.pageYoffset / window.scrollY 。 可以使用 scroll() 、 scrollTo() 和 scrollBy() 方法滚动页面。这3个方法都接收表示相对 视口距离的和坐标,这两个参数在前两个方法中表示要滚动到的坐标,在最后一个方法中表示滚动的距 离。
window.screenX,window.screenY
window.screenX和window.screenY属性,返回浏览器窗口左上角相对于当前屏幕左上角的水平距离和垂直距离(单位像素)。这两个属性只读。
window.scrollX,window.scrollY
window.scrollX属性返回页面的水平滚动距离,window.scrollY属性返回页面的垂直滚动距离,单位都为像素。这两个属性只读。
注意,这两个属性的返回值不是整数,而是双精度浮点数。如果页面没有滚动,它们的值就是0。
举例来说,如果用户向下拉动了垂直滚动条75像素,那么window.scrollY就是75左右。用户水平向右拉动水平滚动条200像素,window.scrollX就是200左右。
window.pageXOffset,window.pageYOffset
window.pageXOffset属性和window.pageYOffset属性,是window.scrollX和window.scrollY别名。
窗口组件属性 返回浏览器的组件对象
组件属性返回浏览器的组件对象。这样的属性有下面几个。
- window.locationbar:地址栏对象
- window.menubar:菜单栏对象
- window.scrollbars:窗口的滚动条对象
- window.toolbar:工具栏对象
- window.statusbar:状态栏对象
- window.personalbar:用户安装的个人工具栏对象
这些对象的visible属性是一个布尔值,表示这些组件是否可见。这些属性只读。
window.locationbar.visible
window.menubar.visible
window.scrollbars.visible
window.toolbar.visible
window.statusbar.visible
window.personalbar.visible
window.isSecureContext 当前窗口是否处在加密环境
window.isSecureContext属性返回一个布尔值,表示当前窗口是否处在加密环境。如果是 HTTPS 协议,就是true,否则就是false。
全局对象属性
全局对象属性指向一些浏览器原生的全局对象。
- window.document:指向document对象,详见《document 对象》一章。注意,这个属性有同源限制。只有来自同源的脚本才能读取这个属性。
- window.location:指向Location对象,用于获取当前窗口的 URL 信息。它等同于document.location属性,详见《Location 对象》一章。
- window.navigator:指向Navigator对象,用于获取环境信息,详见《Navigator 对象》一章。
- window.history:指向History对象,表示浏览器的浏览历史,详见《History 对象》一章。
- window.localStorage:指向本地储存的 localStorage 数据,详见《Storage 接口》一章。
- window.sessionStorage:指向本地储存的 sessionStorage 数据,详见《Storage 接口》一章。
- window.console:指向console对象,用于操作控制台,详见《console 对象》一章。
- window.screen:指向Screen对象,表示屏幕信息,详见《Screen 对象》一章。
window 对象的方法
同步对话框 alert(),prompt(),confirm()
window.alert()警告框、window.prompt()提示框、window.confirm()确认框都是浏览器与用户互动的全局方法。它们会弹出不同的对话框,要求用户做出回应。注意,这三个方法弹出的对话框,都是浏览器统一规定的式样,无法使用CSS设置。
此外,这些对话框都是同步的模态对话框,即在它们显示的时候,代码会停止执 行,在它们消失以后,代码才会恢复执行。
window.alert()方法弹出的对话框,只有一个“确定”按钮,往往用来通知用户某些信息。用户只有点击“确定”按钮,对话框才会消失。对话框弹出期间,浏览器窗口处于冻结状态,如果不点“确定”按钮,用户什么也干不了。
window.alert()方法的参数只能是字符串,没法使用 CSS 样式,但是可以用\n指定换行。
alert("这是一个警告框!");
alert('本条提示\n分成两行');
window.prompt()方法弹出的对话框,提示文字的下方,还有一个输入框,要求用户输入信息,并有“确定”和“取消”两个按钮。它往往用来获取用户输入的数据。
window.prompt("sometext","defaultvalue");
function myFunction(){
var x;
var person = window.prompt("请输入你的名字","小明");
if (person!=null && person!=""){
x="你好 " + person + "! 今天感觉如何?";
document.getElementById("demo").innerHTML=x;
}
}
上面代码会跳出一个对话框,文字提示为“请输入你的名字”,要求用户在对话框中输入自己的名字(默认显示小明)。用户填入的值,会作为返回值存入变量person。
window.prompt()的返回值有两种情况,可能是字符串(有可能是空字符串),也有可能是null。具体分成三种情况。
- 用户输入信息,并点击“确定”,则用户输入的信息就是返回值。
- 用户没有输入信息,直接点击“确定”,则输入框的默认值就是返回值。
- 用户点击了“取消”(或者按了 ESC 按钮),则返回值是null。
window.prompt()方法的第二个参数是可选的,但是最好总是提供第二个参数,作为输入框的默认值。
window.confirm()方法弹出的对话框,除了提示信息之外,只有“确定”和“取消”两个按钮,往往用来征询用户是否同意。
confirm方法返回一个布尔值,如果用户点击“确定”,返回true;如果用户点击“取消”,则返回false。
window.confirm("这是一个确认框");
function myFunction(){
var x;
var r=window.confirm("按下按钮!");
if (r==true){
x="你按下了\"确定\"按钮!";
}
else{
x="你按下了\"取消\"按钮!";
}
document.getElementById("demo").innerHTML=x;
}
异步对话框 find() , print()
JavaScript还可以显示另外两种对话框: find() 和 print() 。这两种对话框都是异步显示的,即 控制权会立即返回给脚本。用户在浏览器菜单上选择“查找”(find)和“打印”(print)时显示的就是这两 种对话框。通过在 window 对象上调用 find() 和 print() 可以显示它们,比如
这两个方法不会返回任何有关用户在对话框中执行了什么操作的信息,因此很难加以利用。此外,因 为这两种对话框是异步的,所以浏览器的对话框计数器不会涉及它们,而且用户选择禁用对话框对它们也 没有影响。
open 新建窗口
window.open方法用于新建另一个浏览器窗口,类似于浏览器菜单的新建窗口选项。它会返回新窗口的引用,如果无法新建窗口,则返回null。
window.open(url, name,'width=400,height=400,top=0,left=0') // 弹出一个窗口
/*
参数1. 新窗口的地址
参数2. 新窗口的名称
参数3. 新窗口大小和显示位置
*/
第三个参数, 即特性字符串,用于指定新窗口的配置。如果没有传第三个参数,则新窗口(或标签页)会带有所有 默认的浏览器特性(工具栏、地址栏、状态栏等都是默认配置)。如果打开的不是新窗口,则忽略第 三个参数。 特性字符串是一个逗号分隔的设置字符串,用于指定新窗口包含的特性。下表列出了一些选项。
window.open() 方法返回一个对新建窗口的引用。这个对象与普通 window 对象没有区别,只是 为控制新窗口提供了方便。例如,某些浏览器默认不允许缩放或移动主窗口,但可能允许缩放或移动 通过 window.open() 创建的窗口。跟使用任何 window 对象一样,可以使用这个对象操纵新打开 的窗口。
计时
setTimeout():未来的某时执行代码
clearTimeout():取消setTimeout()
在浏览器中,主计时器函数是 Window
接口的一部分,它具有一些其他函数和对象。该接口使其所有元素在主 JavaScript 全局可用。这就是您可以直接在浏览器控制台中执行 setTimeout
的原因。
在 Node 中,计时器是 global
对象的一部分,其行为类似于浏览器的 Window
接口。你可以在此处查看 Node 中的计时器源代码https://github.com/nodejs/node/blob/master/lib/timers.js。
// 设置超时任务
let timeoutId = setTimeout(() => alert("Hello world!"), 1000);
// 取消超时任务
clearTimeout(timeoutId);
全局对象属性 详解
navigator 浏览器信息
navigator.appName // 浏览器名称
navigator.appVersion // 浏览器版本
navigator.language // 语言
navigator.platform:// 操作系统
navigator.userAgent // User-Agent
/*
navigator === window.navigator
浏览器信息容易被更改,读取信息不一定准确
*/
screen 当前显示分辨率
screen.width
screen.height
/*
screen === window.screen
*/
location URL相关
location 是最有用的BOM对象之一,提供了当前窗口中加载文档的信息,以及通常的导航功能。 这个对象独特的地方在于,它既是 window 的属性,也是 document 的属性。
也就是说, window.location 和 document.location 指向同一个对象。 location 对象不仅保存着当前加载文档的信息,也保存着把URL解析为离散片段后能够通过属性访问的信息。这些解析后的属性在下表中 有详细说明( location 前缀是必需的)。
假设浏览器当前加载的URL是http://foouser:barpassword@www.wrox.com:80/WileyCDA/?q=javascript#contents, location 对象的内容如下表所示。
location.protocol // https: | 协议
location.host // www.jmjc.com | 主机
location.port // 端口号
location.href // https://www.jmjc.tech/ | 当前地址
location.pathname; // /less/77 | 当前目录
location.search // ?a=1&b=2 | 参数
location.reload() // 刷新当前页面
location.assign(URL) // 跳转到 URL
location.href = URL // 跳转到 URL
/*
location === window.location
*/
查询字符串
location 的多数信息都可以通过上面的属性获取。但是URL中的查询字符串并不容易使用。虽然 location.search 返回了从问号开始直到URL末尾的所有内容,但没有办法逐个访问每个查询参数。 下面的函数解析了查询字符串,并返回一个以每个查询参数为属性的对象
let getQueryStringArgs = function() {
// 取得没有开头问号的查询字符串
let qs = (location.search.length > 0 ? location.search.substring(1) :""),
// 保存数据的对象
args = {};
// 把每个参数添加到args对象
for (let item of qs.split("&").map(kv => kv.split("="))) {
let name = decodeURIComponent(item[0]),
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
这个函数首先删除了查询字符串开头的问号,当然前提是 location.search 必须有内容。解析后 的参数将被保存到 args 对象,这个对象以字面量形式创建。接着,先把查询字符串按照 & 分割成数 组,每个元素的形式为 name=value 。 for 循环迭代这个数组,将每一个元素按照 = 分割成数组,这 个数组第一项是参数名,第二项是参数值。参数名和参数值在使用 decodeURIComponent() 解码后 (这是因为查询字符串通常是被编码后的格式)分别保存在 name 和 value 变量中。最后, name 作 为属性而 value 作为该属性的值被添加到 args 对象。这个函数可以像下面这样使用:
// 假设查询字符串为?q=javascript&num=10
let args = getQueryStringArgs();
alert(args["q"]); // "javascript"
alert(args["num"]); // "10"
URLSearchParams
URLSearchParams 提供了一组标准API方法,通过它们可以检查和修改查询字符串。给 URLSearchParams 构造函数传入一个查询字符串,就可以创建一个实例。这个实例上暴露了 get() 、 set() 和 delete() 等方法,可以对查询字符串执行相应操作。
let qs = "?q=javascript&num=10";
let searchParams = new URLSearchParams(qs);
alert(searchParams.toString()); // " q=javascript&num=10"
searchParams.has("num"); // true
searchParams.get("num"); // 10
searchParams.set("page", "3");
alert(searchParams.toString()); // " q=javascript&num=10&page=3"
searchParams.delete("q");
alert(searchParams.toString()); // " num=10&page=3"
大多数支持 URLSearchParams 的浏览器也支持将 URLSearchParams 的实例用作可迭代对象:
let qs = "?q=javascript&num=10";
let searchParams = new URLSearchParams(qs);
for (let param of searchParams) {
console.log(param);
}
// ["q", "javascript"]
// ["num", "10"]
操作地址
assign() 打开新url页面
首先,最常见的是使用 assign() 方法并传入 一个URL
location.assign("http://www.wrox.com");
这行代码会立即启动导航到新URL的操作,同时在浏览器历史记录中增加一条记录。如果给 location.href 或 window.location 设置一个URL,也会以同一个URL值调用 assign() 方法。 比如,下面两行代码都会执行与显式调用 assign() 一样的操作
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
在这3种修改浏览器地址的方法中,设置 location.href 是最常见的。
修改 location 对象的属性也会修改当前加载的页面。其中, hash 、 search 、 hostname 、 pathname 和 port 属性被设置为新值之后都会修改当前URL,如下面的例子所示:
除了 hash 之外,只要修改 location 的一个属性,就会导致页面重新加载新URL。
replace() 打开新页面而不增加记录
在以前面提到的方式修改URL之后,浏览器历史记录中就会增加相应的记录。当用户单击“后退”按钮 时,就会导航到前一个页面。如果不希望增加历史记录,可以使用 replace() 方法。这个方法接收一 个URL参数,但重新加载后不会增加历史记录。调用 replace() 之后,用户不能回到前一页。
location.replace("http://www.wrox.com/"),
reload()重新加载
能重新加载当前显示的页面。调用 reload() 而不传 参数,页面会以最有效的方式重新加载。也就是说,如果页面自上次请求以来没有修改过,浏览器可能会 从缓存中加载页面。如果想强制从服务器重新加载,可以像下面这样给 reload() 传个 true
location.reload(); // 重新加载,可能是从缓存加载
location.reload(true); // 重新加载,从服务器加载
脚本中位于 reload() 调用之后的代码可能执行也可能不执行,这取决于网络延迟和系统资源等因 素。为此,最好把 reload() 作为最后一行代码。
获取当前路径
var currentPageUrl = "";
if (typeof this.href === "undefined") {
currentPageUrl = document.location.toString().toLowerCase();
} else {
currentPageUrl = this.href.toString().toLowerCase();
}
document
document.referrer // 上一次访问的地址
/*
document === window.document
document 是重要的独立的章节,在 “DOM”,这里只列举一个跟获取信息相关的
*/
history
浏览器的浏览历史
history.back() // 后退一个页面
history.forward() // 前进一个页面
// 后退一页
history.go(-1);
// 前进一页
history.go(1);
// 前进两页
history.go(2);
/*
history === window.history
该方法相当于我们点浏览器上方的 <- ->
*/
window.history.pushState
history.scrollRestoration 刷新后滚动条位置
无论是哪个浏览器,都有这样一个体验细节。
那就是,如果浏览器不是强制刷新(Ctrl + F5),而是普通刷新(点击刷新按钮,或者按下 F5 刷新),则页面重新载入完毕后大概率会调到之前访问的位置。
浏览器已经提供了原生的 API,可以轻松实现浏览器滚动后每次都回到顶部的能力
if (history.scrollRestoration) {
history.scrollRestoration = 'manual';
}
history.scrollRestoration 支持下面两个属性值:
auto
默认值,表示滚动位置会被存储。
manual
单词的意思就是手动。表示,滚动的位置不会被存储。
兼容性
兼容性很不错,现代浏览器很早就支持了,移动端放心使用。
Cookie
URL
URL接口是一个构造函数,浏览器原生提供,具体方法在《WebAPI》的URL接口中说明。
404 - Not Found · 语雀