window是BOM的核心对象,表示浏览器的一个实例。在浏览器中,window对象有双重角色,它是通过JS访问浏览器窗口的一个接口,也是Global对象。任何在全局作用域中声明的变量和函数都会变成window对象的属性和方法。
虽然全局变量也是window对象的属性,但是与直接在window上定义的属性也是有点不同。全局变量不能通过delete操作符删除,而直接在window上定义的属性则可以。另外,直接访问未声明的变量会抛出错误,而通过window对象访问则不会,只是返回undefined。
var p1 = 'p1';
window.p2 = 'p2';
delete window.p1; // 无法删除
delete window.p2;
console.log(window.p1); // 输出'p1'
console.log(window.p2); // undefined
console.log(window.p3); // undefined
console.log(p3); // 出错
如果页面中包含框架(frame),则每个框架都有自己的window对象,并且保存在frames集合中,可以通过数值索引或者框架名称来访问相应的window对象。举个例子,对于下面代码,可以使用window.frames[0]或者window.frames[“top”]来访问名字为”top”的框架。
<html>
<head>
<title>Framestitle>
head>
<frameset rows="160, *">
<frame src="top-frame.html" name="top">frame>
<frameset cols="50%, 50%">
<frame src="left-frame.html" name="left">frame>
<frame src="right-frame.html" name="right">frame>
frameset>
frameset>
html>
通过window对象的属性可以获取和调节窗口位置。使用下面代码可以跨浏览器获取窗口左边和上边的位置。使用moveTo和moveBy方法可以移动窗口调节位置,moveTo接受的参数是新位置的坐标,moveBy接受的参数是水平和垂直方向上的偏移量。(移动窗口的方法在某些浏览器中可能被禁用;这两个方法不适用于框架)
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
window.moveTo(0, 0); // 移动到屏幕左上角
window.moveBy(0, 100); // 向下移动100像素
通过window对象的属性可以获取和调节窗口大小。使用resizeTo和resizeBy方法可以调节窗口大小,resizeTo接受的参数是窗口的新宽度和高度,resizeBy接受的参数是新宽度高度与原来的宽度高度的差值。
window对象的setTimeout方法用于超时调用,它接受两个参数:需要执行的代码和以毫秒为单位的时间数值。执行代码可以以字符串或函数的形式进行传参。这个方法的运行效果是使得传入参数的执行代码会在经过一段时间之后才开始执行。传递字符串可能导致性能损失,因此应该尽量以函数的形式传递需要执行的代码。另外,JS是一个单线程的解释器,一定时间内只能执行一段代码,为了控制要执行的代码,就有一个JS任务队列。这些任务会按照它们被添加到队列的顺序执行。setTimeout的第二个参数实际上是告诉JS再过多久之后把当前任务添加到任务队列,如果队列是空的,那么添加后任务就会马上执行,否则还需要等待队列前面的代码执行完之后才执行setTimeout第一个参数里面的任务。也就是说,即便我第二个参数指定为1秒,但是1秒过后任务不一定会准时执行。
// 以字符串形式传入需要执行的代码,1000毫秒后输出'23333'
setTimeout("console.log('23333')", 1000);
// 以函数形式传入需要执行的代码,2000毫秒后输出'hehe~'
setTimeout(function() {
console.log('hehe~');
}, 2000);
超时调用其他注意点:调用setTimeout之后会返回一个数值ID,通过这个ID可以来取消某个对应的超时调用。调用clearTimeout,将ID作为参数传入,即可取消该ID所对应的超时调用。超时调用的代码都是在全局作用域中执行,this的值在非严格模式下指向window对象,严格模式下为undefined。
间歇调用与超时调用类似,只不过它是按照指定的时间间隔重复执行代码,知道间歇调用被取消或者页面被卸载。设置间歇调用的方法是setInterval,接受的参数与setTimeout相同。setInterval方法也会返回一个ID,对应一个特定的间歇调用。取消间歇调用时,通过clearInterval方法即可完成。间歇调用也是在全局作用域中执行,this的值与超时调用一样。
var num = 1;
var ID = null;
ID = setInterval(function() {
console.log(num);
num += 1;
if (num == 5) {
clearInterval(ID);
}
}, 500);
一般认为,使用超时调用模拟间歇调用是一种最佳模式,如以下代码示例。在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动,而使用超时调用,则可以完全避开这个缺点,保证先后顺序。
var num = 1;
function func() {
console.log(num);
num += 1;
if (num < 5) {
setTimeout(func, 500);
}
}
setTimeout(func, 500);
location对象提供了与当前窗口中加载的文档有关的信息,还提供一些导航功能。location对象既是window对象的属性,也是document对象的属性,也就是说,window.location和document.location引用的是同一个对象。location对象可以将URL解析为独立的片段,让开发人员可以通过不同的的属性访问这些片段。下表列出location对象的所有属性并给出例子说明。
属性名 | 例子 | 说明 |
---|---|---|
hash | “#contents” | URL中的hash(#号后面跟着的字符串,锚) |
host | “www.wrox.com:80” | 服务器名称和端口号 |
hostname | “www.wrox.com” | 服务器名称 |
href | “http://www.wrox.com” | 完整的URL |
pathname | “/WileyCDA” | URL中的路径名 |
port | “80” | 端口号 |
protocol | “http” | 协议 |
search | “?q=javascript” | 查询字符串 |
查询字符串:通过search属性可以获取查询字符串,但search属性返回的是从问号到URL结尾的所有内容,因此不能很好地方便我们访问查询字符串中的属性。在使用search属性获取查询字符串之后还需要再对其进行解析,然后才可以获取我们想要获得的属性和属性值。可以使用如下代码来解析查询字符串:
function getQueryStringArgs() {
var qs = (location.search.length > 0 ? location.search.substring(1) : "");
var args = {};
var items = qs.length ? qs.split("&") : [];
var item = null, name = null, value = null;
for (var i = 0; i < items.length; ++i) {
item = items[i].split("=");
name = decodeURIComponent(item[0]); // 查询字符串一般是被编码过的,所以这里需要解码
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
位置操作:使用location对象可以改变浏览器的位置。下面给出代码示例。每次修改location的属性(hash属性除外),页面都会以新的URL重新加载,页面刷新后浏览器的历史记录中会生成一条新纪录。如果想要仅跳转页面但是不产生历史记录,可以通过replace方法来实现。最后,location还有一个与位置相关的方法,reload,重新加载页面。
location.assign("http://www.wrox.com");
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
// 上面3种示例都是直接修改整个URL,下面给出只修改URL中的某个部分来改变位置的例子
location.hash = "#section1";
location.search = "?q=javascript";
location.hostname = "www.yahoo.com";
location.pathname = "mydir";
location.port = 8080;
// 使用replace不产生历史记录
location.replace("http://www.wrox.com");
// 重新加载页面
location.reload(); // 从服务器或浏览器缓存中重新加载
location.reload(true); // 从服务器重新加载