BOM是浏览器对象模型
Window对象
- BOM 的核心对象是window,它表示浏览器的一个实例。
- 在浏览器中,window 对象有双重角色,它既是通过JavaScript访问浏览器窗口的一个接口,又是ECMAScript 规定的Global 对象。
- 在网页中定义的任何一个对象、变量和函数,都以window作为其Global对象,因此有权访问
parseInt()等方法。
1、全局作用域
- 由于window 对象同时扮演着ECMAScript中Global对象的角色,因此所有在全局作用域中声明的变量、函数都会变成window 对象的属性和方法。
var age = 29;
function sayAge(){
alert(this.age);
}
alert(window.age); //29
sayAge(); //29
window.sayAge(); //29
- 定义全局变量与在window对象上直接定义属性还是有一点差别:全局变量不能通过delete 操作符删除,而直接在window 对象上的定义的属性可以。
var age = 29;
window.color = "red";
//在IE < 9 时抛出错误,在其他所有浏览器中都返回false
delete window.age;
//在IE < 9 时抛出错误,在其他所有浏览器中都返回true
delete window.color; //returns true
alert(window.age); //29
alert(window.color); //undefined
- 尝试访问未声明的变量会抛出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在。
//这里会抛出错误,因为oldValue 未定义
var newValue = oldValue;
//这里不会抛出错误,因为这是一次属性查询
//newValue 的值是undefined
var newValue = window.oldValue;
2、窗口关系和框架
- 如果页面中包含框架,那么每个框架都有自己的window对象,并保存在frames集合中。
- 在frames集合中,可以通过数值索引(从0开始,从左至右,从上到下)或者框架名称来访问相应的window 对象。
- 每个window 对象都有一个name 属性,其中包含框架的名称。
<html>
<head>
<title>Frameset Example</title>
</head>
<frameset rows="160,*">
<frame src="frame.htm" name="topFrame">
<frameset cols="50%,50%">
<frame src="anotherframe.htm" name="leftFrame">
<frame src="yetanotherframe.htm" name="rightFrame">
</frameset>
</frameset>
</html>
- top 对象始终指向最高(最外)层的框架,也就是浏览器窗口。使用它可以确保在一个
框架中正确地访问另一个框架. - 因为对于在一个框架中编写的任何代码来说,其中的window对象指向的都是那个框架的特定实例,而非最高层的框架。
- parent(父)对象始终指向当前框架的直接上层框架。
- 在某些情况下,parent 有可能等于top;但在没有框架的情况下,parent 一定等于
top(此时它们都等于window)
3、窗口位置
- 用来确定和修改window 对象位置的属性和方法有很多
- IE、Safari、Opera 和Chrome都提供了screenLeft和screenTop属性,分别用于表示窗口相对于屏幕左边和上边的位置。
- Firefox 则在screenX和screenY属性中提供相同的窗口位置信息,Safari和Chrome也同时支持这两个属性。
//跨浏览器获取窗口左边和上边的位置
var leftPos = (typeof window.screenLeft == "number") ?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ?
window.screenTop : window.screenY;
- 注意问题:如果window 对象是最外层对象,而且浏览器窗口紧贴屏幕最上端——即y 轴坐标为0,那么screenTop的值就是位于页面可见区域上方的浏览器工具栏的像素高度。在Chrome、Firefox和Safari中,screenY或screenTop中保存的是整个浏览器窗口相对于屏幕的坐标值,即在窗口的y 轴坐标为0 时返回0。
- 兼容问题:Firefox、Safari和Chrome始终返回页面中每个框架的top.screenX和top.screenY 值。即使在页面由于被设置了外边距而发生偏移的情况下,相对于window对象使用screenX 和screenY每次也都会返回相同的值。而IE和Opera则会给出框架相对于屏幕边界的精确坐标值。最终结果,就是无法在跨浏览器的条件下取得窗口左边和上边的精确坐标值
- 使用moveTo()和moveBy()方法可能将窗口精确地移动到一个新位置。这两个方法都接收两个参数,其中moveTo()接收的是新位置的x和y坐标值,而moveBy()接收的是在水平和垂直方向上移动的像素数。
//将窗口移动到屏幕左上角
window.moveTo(0,0);
//将窗向下移动100 像素
window.moveBy(0,100);
//将窗口移动到(200,300)
window.moveTo(200,300);
//将窗口向左移动50 像素
window.moveBy(-50,0);
- 这两个方法可能会被浏览器禁用;而且,在Opera和IE7(及更高版本)中默认就是禁用的
4、窗口大小
- IE9+、Firefox、Safari、Opera和Chrome均为此提供了4个属性:innerWidth、innerHeight、outerWidth 和outerHeight。
- 在IE9+、Safari 和Firefox中,outerWidth和outerHeight返回浏览器窗口本身的尺寸(无论是从最外层的window 对象还是从某个框架访问)
- 在Opera 中,outerWidth和outerHeight的值表示页面视图容器(Opera中单个标签页对应的浏览器窗口)的大小
- innerWidth 和innerHeight则表示该容器中页面视图区的大小(减去边框宽度)
- 在Chrome 中,outerWidth、outerHeight与innerWidth、innerHeight返回相同的值,即视口(viewport)大小而非浏览器窗口大小。
- IE8 及更早版本没有提供取得当前浏览器窗口尺寸的属性;不过,它通过DOM提供了页面可见区域的相关信息。虽然最终无法确定浏览器窗口本身的大小,但却可以取得页面视口的大小。
var pageWidth = window.innerWidth,
pageHeight = window.innerHeight;
if (typeof pageWidth != "number"){
if (document.compatMode == "CSS1Compat"){
//混杂模式
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
- 对于移动设备,window.innerWidth和window.innerHeight保存着可见视口,也就是屏幕上可见页面区域的大小。移动IE浏览器不支持这些属性,但通过document.documentElement.clientWidth 和document.documentElement.clientHeihgt提供了相同的信息随着页面的缩放,这些值也会相应变化。
- 在其他移动浏览器中,document.documentElement度量的是布局视口,即渲染后页面的实际大小(与可见视口不同,可见视口只是整个页面中的一小部分)
- 移动IE 浏览器把布局视口的信息保存在document.body.clientWidth和document.body.clientHeight 中。这些值不会随着页面缩放变化。
- 使用resizeTo()和resizeBy()方法可以调整浏览器窗口的大小。这两个方法都接收两个参数,其中resizeTo()接收浏览器窗口的新宽度和新高度,而resizeBy()接收新窗口与原窗口的宽度和高度之差。
//调整到100×100
window.resizeTo(100, 100);
//调整到200×150
window.resizeBy(100, 50);
//调整到 300×300
window.resizeTo(300, 300);
5、导航和打开窗口
- 使用window.open()方法既可以导航到一个特定的URL,也可以打开一个新的浏览器窗口。这个方法可以接收4个参数:要加载的URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值
//等同于< a href="http://www.wrox.com" target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
/**如果有一个名叫"topFrame"的窗口或者框架,就会在该窗口或框架加载这个URL;否则,就会创建一个新窗口并将其命名为"topFrame"。**/
- 如果给window.open()传递的第二个参数并不是一个已经存在的窗口或框架,那么该方法就会根据在第三个参数位置上传入的字符串创建一个新窗口或新标签页.
- 如果没有传入第三个参数,那么就会打开一个带有全部默认设置(工具栏、地址栏和状态栏等)的新浏览器窗口。
- 第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。下表列出了可以出现在这个字符串中的设置选项。
设 置 | 值 | 说 明 |
---|---|---|
fullscreen | yes或no | 表示浏览器窗口是否最大化。仅限IE |
height | 数值 | 表示新窗口的高度。不能小于100 |
left | 数值 | 表示新窗口的左坐标。不能是负值 |
location | yes或no | 表示是否在浏览器窗口中显示地址栏。不同浏览器的默认值不同。如果设置为no,地址栏可能会隐藏,也可能会被禁用(取决于浏览器) |
menubar | yes或no | 表示是否在浏览器窗口中显示菜单栏。默认值为no |
resizable | yes或no | 表示是否可以通过拖动浏览器窗口的边框改变其大小。默认值为no |
scrollbars | yes或no | 表示如果内容在视口中显示不下,是否允许滚动。默认值为no |
status | yes或no | 表示是否在浏览器窗口中显示状态栏。默认值为no |
toolbar | yes或no | 表示是否在浏览器窗口中显示工具栏。默认值为no |
top | 数值 | 表示新窗口的上坐标。不能是负值 |
width | 数值 | 表示新窗口的宽度。不能小于100 |
window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");
/**打开一个新的可以调整大小的窗口,窗口初始大小为400×400 像素,并且距屏幕上沿
和左边各10 像素。**/
- window.open()方法会返回一个指向新窗口的引用。通过这个返回的对象,可以像操作其他窗口一样操作新打开的窗口。
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
//调整大小
wroxWin.resizeTo(500,500);
//移动位置
wroxWin.moveTo(100,100);
//调用close()方法还可以关闭新打开的窗口。对于浏览器的主窗口,如果没有
//得到用户的允许是不能关闭它的
wroxWin.close();
alert(wroxWin.closed); //true
- 新创建的window 对象有一个opener属性,其中保存着打开它的原始窗口对象。这个属性只在弹出窗口中的最外层window对象(top)中有定义,而且指向调用window.open()的窗口或框架。
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
alert(wroxWin.opener == window); //true
- 在Chrome中,将新创建的标签页的opener属性设置为null,即表示在单独的进程中运行新标签页.
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
wroxWin.opener = null;
/**将opener 属性设置为null就是告诉浏览器新创建的标签页不需要与打开它的标签页通信,因此可以在独立的进程中运行。标签页之间的联系一旦切断,将没有办法恢复。**/
- 大多数浏览器都内置有弹出窗口屏蔽程序,而没有内置此类程序的浏览器,也可以安装Yahoo!,Toolbar 等带有内置屏蔽程序的实用工具.
- 如果是浏览器内置的屏蔽程序阻止的弹出窗口,那么window.open()很可能会返回null。此时,只要检测这个返回的值就可以确定弹出窗口是否被屏蔽了。
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null){
alert("The popup was blocked!");
}
- 如果是浏览器扩展或其他程序阻止的弹出窗口,那么window.open()通常会抛出一个错误。因此,要想准确地检测出弹出窗口是否被屏蔽,必须在检测返回值的同时,将对window.open()的调用封装在一个try-catch 块中。
var blocked = false;
try {
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null){
blocked = true;
}
} catch (ex){
blocked = true;
}
if (blocked){
alert("The popup was blocked!");
}
6、间歇调用和超时调用
- JavaScript 是单线程语言,但它允许通过设置超时值和间歇时间值来调度代码在特定的时刻执行。前者是在指定的时间过后执行代码,而后者则是每隔指定的时间就执行一次代码。
- 超时调用需要使用window对象的setTimeout()方法,它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。
- 第一个参数可以是一个包含JavaScript 代码的字符串,也可以是一个函数。
//由于传递字符串可能导致性能损失,不建议传递字符串!
setTimeout("alert('Hello world!') ", 1000);
//推荐的调用方式
setTimeout(function() {
alert("Hello world!");
}, 1000);
- 第二个参数是一个表示等待多长时间的毫秒数,但经过该时间后指定的代码不一定会执行。
【原因】:JavaScript是一个单线程序的解释器,因此一定时间内只能执行一段代码。为了控制要执行的代码,就有一个JavaScript任务队列。这些任务会按照将它们添加到队列的顺序执行。setTimeout()的第二个参数告诉JavaScript再过多长时间把当前任务添加到队列中。如果队列是空的,那么添加的代码会立即执行;如果队列不是空的,那么它就要等前面的代码执行完了以后再执行。 - 调用setTimeout()之后,该方法会返回一个数值ID,表示超时调用。这个超时调用ID 是计划执行代码的唯一标识符,可以通过它来取消超时调用。
- 要取消尚未执行的超时调用计划,可以调用clearTimeout*()方法并将相应的超时调用ID 作为参数传递给它。
//设置超时调用
var timeoutId = setTimeout(function() {
alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);
- 间歇调用会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载.
- 设置间歇调用的方法是setInterval(),它接受的参数与setTimeout()相同:要执行的代码(字符串或函数)和每次执行之前需要等待的毫秒数。
//不建议传递字符串!
setInterval ("alert('Hello world!') ", 10000);
//推荐的调用方式
setInterval (function() {
alert("Hello world!");
}, 10000);
- 调用setInterval()方法同样也会返回一个间歇调用ID,该ID可用于在将来某个时刻取消间歇调用。要取消尚未执行的间歇调用,可以使用clearInterval()方法并传入相应的间歇调用ID。
- 取消间歇调用的重要性要远远高于取消超时调用,因为在不加干涉的情况下,间歇调用将会一直执行到页面卸载。
var num = 0;
var max = 10;
var intervalId = null;
function incrementNumber() {
num++;
//如果执行次数达到了max 设定的值,则取消后续尚未执行的调用
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);
- 这个模式也可以使用超时调用来实现,在使用超时调用时,没有必要跟踪超时调用ID,因为每次执行代码之后,如果不再设置另一次超时调用,调用就会自行停止。
- 一般认为,使用超时调用来模拟间歇调用的是一种最佳模式。在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动。使用超时调用,则完全可以避免这一点。
var num = 0;
var max = 10;
function incrementNumber() {
num++;
//如果执行次数未达到max 设定的值,则设置另一次超时调用
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);
7、系统对话框
- 浏览器通过alert()、confirm()和prompt()方法可以调用系统对话框向用户显示消息。
- 它们的外观由操作系统及(或)浏览器设置决定,而不是由CSS 决定。
- 通过这几个方法打开的对话框都是同步和模态的。也就是说,显示这些对话框的时候代码会停止执行,而关掉这些对话框后代码又会恢复执行。
//使用alert()生成“警告”对话框
alert("Hello World!");
//调用confirm()方法生成确认框,包含【确认】和【取消】
if (confirm("Are you sure?")) {
alert("I'm so glad you're sure! ");
} else {
alert("I'm sorry to hear you're not sure. ");
}
/**调用prompt()方法生成“提示”框,提示框中除了包含【确认】和【取消】外,还会显示一个文本输入域,以供用户在其中输入内容。
prompt()方法接受两个参数:要显示给用户的文本提示和文本输入域的默认值(可以是一个空字符串)。**/
var result = prompt("What is your name? ", "");
if (result !== null) {
alert("Welcome, " + result);
}
- 如果当前脚本在执行过程中会打开两个或多个对话框,那么从第二个对话框开始,每个对话框中都会显示一个复选框,以便用户阻止后续的对话框显示,除非用户刷新页面。
- 还有两个可以通过JavaScript打开的对话框,即“查找”和“打印”。这两个对话框都是异步显示的,能够将控制权立即交还给脚本。
//显示“打印”对话框
window.print();
//显示“查找”对话框
window.find();