<h1 id="8">第8章 BOM</h1>
本章内容主要是
- 理解window对象
- 控制窗口、框架和弹出窗口
- 利用location对象中的页面信息
- 使用navigator对象了解浏览器
<h2 id="8.1">8.1 window对象</h2>
- BOM的核心对象是window,它表示浏览器的一个实例。
- window对象既是通过JS访问浏览器窗口的一个接口,又是ES规定的Global对象
- 网页中定义的热呢一个对象、变量和函数,都以window作为其Global对象
<h3 id="8.1.1">8.1.1 全局作用域</h3>
所有在全局作用域中声明的变量、函数都会变成window对象的属性和方法
定义全局变量和直接在window对象上定义属性有一点差别:全局变量不能通过delete操作符删除,而直接在window对象上定义的属性可以。这是因为使用var语句添加的window属性有一个名为[[Configurable]]的特性,值被设为false
-
尝试访问未声明的变量会抛出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在
//这样不会有错误。值是undefined var newValue = window.oldValue; //抛出错误 var newValue = oldValue;
<h3 id="8.1.2">8.1.2 窗口关系及框架</h3>
- 如果页面中包含框架(像frameset这种),则每个框架都有自己的window对象,并且保存在frames集合中。
- 在frames集合中,可以通过数值索引(0开始,从左到右,从上到下)或者框架名称来访问相应的window对象
- 每个window对象都有一个name属性,其中包含框架的名称
top对象:
- top对象始终指向最高(最外)层的框架,也就是浏览器窗口,使用它可以确保在一个框架中正确地访问另一个框架
window对象:
- 在一个框架中的window指向的都是自己那个框架,不是最高层的
parent对象:
- 始终指向当前框架的直接上层框架
- 在某些情况下,parent有可能等于top;在没有框架的情况下,parent一定等于top(都是window)
self对象:
- 始终指向window
- 引入self只是为了与top和parent对应起来
<h3 id="8.1.3">8.1.3 窗口关系及框架</h3>
跨浏览器取得窗口左边和上边的位置:
var leftPos = (typeof window.screenLeft == "number")?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number")?
window.scrrenTop : window.screenY;
这是因为Safari、Opera和Chrome中存在screenLeft和screenTop属性,而在Firefox中是scrrenX和ScreenY
无法在跨浏览器的条件下取得窗口左边和上边的精确坐标值,因为在Firefox和Safari中返回的是整个浏览器窗口相对于屏幕的坐标值,在IE、Opera和Chrome中返回的是页面可见区域(不包括工具栏)到屏幕左边和上边的值
将窗口精确地移动到一个新位置的方法:
这两种方法可能会被浏览器禁用。且不适用于框架,只对最外层的window对象使用
-
moveTo()
- 参数:新位置的x和y坐标
-
moveBy()
- 参数:在水平和垂直方向上移动的像素数
<h3 id="8.1.4">8.1.4 窗口大小</h3>
不同浏览器中返回的innerWidth、innerHeight、outerWidth和outerHeight不一样,因此无法最终确定浏览器窗口本身的大小,但可以取得页面视口的大小
var pageWidth = wimdow.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对象使用
-
resizeTo():
- 参数:浏览器窗口的新宽度和新高度
-
resizeBy():
- 参数:新窗口与原窗口的宽度和高度之差
<h3 id="8.1.5">8.1.5 导航和打开窗口</h3>
window.open():
-
参数:要加载的URL、窗口目标、一个特性字符串、一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值
第一个参数:通常只需传递第一个参数。
-
第二个参数:
-
该参数是已有窗口或框架的名称
- 在指定的窗口或框架中加载指定URL
- 代码:
//等同于<a href="http://www.baidu.com/" target="topFrame"></a>
window.open("http://www.baidu.com/","topFrame");
- 如果没有窗口或框架的名称是topFrame,就会创建一个新窗口并将其命名为topFrame
_self
_parent
_top
_blank
-
-
第三个参数:
如果第二个参数并不是已经存在的窗口或框架,那么就会根据在第三个参数位置上传入的字符串创建一个新窗口或新标签页。如果没有第三个参数,就会打开一个带有全部默认设置的新浏览器窗口
在不打开新窗口的情况下,会忽略第三个参数
是一个用逗号分隔的设置字符串,表示新窗口的特性
-
整个特性字符串中不能有空格,比如:
window.open("http://www.baidu.com/","topFrame","height=400,width=400");
第四个参数:只在不打开新窗口的情况下使用
-
返回:一个指向新窗口的引用
用途:可以针对 通过window.open()创建的窗口 调整大小或移动位置
-
代码:
var wroxWin = window.open("http://www.baidu.com/","wroxWindow","height=400,width=400"); wroxWin.resizeTo(500,500); wroxWin.moveTo(100,100)
wroxWin.close()
还可以关闭这个新打开的窗口要注意的是对于浏览器的主窗口,如果没有得到用户允许是不能关闭的(除了弹出窗口可以调用
top.close()
关闭)
-
opener属性
- 定义于新窗口的最外层window对象(top)中,指向原始窗口(调用
window.open()
的窗口或框架) - 当把opener属性设置为null时,就是告诉浏览器新建的标签页不需要与打开它的标签页通信,因此可以在独立的进程中运行。标签页的联系一旦切断,将没有办法恢复
- 定义于新窗口的最外层window对象(top)中,指向原始窗口(调用
弹出窗口屏蔽程序
内置的屏蔽程序阻止弹出窗口:window.open()返回null
-
扩展或其他程序阻止弹出窗口:抛出一个错误
因此准确检测出弹出窗口是否被屏蔽的代码如下:var blocked = false;
try {
var wroWin = window.open(http://www.baidu.com/","_blank");
if(wroWin == null){
blocked = true;
}
} catch (ex){
blocked = true;
}
if(blocked){
alert("The popup was blocked");
}
<h3 id="8.1.6">8.1.6 间歇调用和超时调用</h3>
JS是单线程语言,但它允许通过设置超时值和间歇时间值来调度代码在特定的时刻执行。
-
超时调用:setTimeOut()
-
参数:要执行的代码和以毫秒表示的时间
- 第一个参数:可以是一个包含JS代码的字符串(同eval()函数里的字符串),也可以是一个函数
- 不建议以字符串作为第一个参数。因为可能导致性能缺失
- 第二个参数:是一个表示等待多长时间的毫秒数。JS是一个单线程的解释器,有一个JS任务队列,这些任务按照将它们添加到队列 的顺序执行。也就是说这个参数只是指定多长时间后把任务添加到队列。但不一定会立即执行(前面可能还有任务)。
-
返回:一个数值ID,表示超时调用
这个超时调用ID是计划执行代码的唯一标识符
-
只要指定的时间尚未过去,就可以取消尚未执行的超时调用计划:传入ID
clearTimeOut(timeoutId);
-
-
间歇调用:setInterval()
- 参数:(与setTimeOut()相同)要执行的代码和以毫秒表示的时间
- 区别:按照指定的时间间隔重复执行代码,直到间歇调用被取消或者页面被卸载
- 返回:间歇调用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);
与以上代码相同功能的超时调用:
var num = 0;
var max = 10;
function incrementMunber(){
num++;
if(num < max){
setTimeout(incrementNumber,500);
}else{
alert("Done");
}
}
setTimeout(incrementNumber,500);
比较上面两段代码,可以看出超时调用不需要跟踪超时调用ID。一般认为,使用超时调用模拟间歇调用是一种最佳模式。在开发环境下,很少使用间歇调用,因为后一个间歇调用可能会在前一个间歇调用结束前启动。所以最好不要使用间歇调用
<h3 id="8.1.7">8.1.7 系统对话框</h3>
以下三个不涉及HTML、CSS、JS
- alert():警告
- confirm():确认
- prompt():提示
- 参数:要显示给用户的文本提示和文本输入域(可以是"")
- 返回:单击OK则返回文本输入域的值,单击cancel或通过其他方式关闭对话框则返回null
以下两个可以通过JS打开的对话框:查找和打印。这两个对话框都是异步显示的,能够将控制权立即交还给脚本。与用户通过浏览器菜单的查找和打印命令打开的对话框相同
- 打印:
window.print();
- 查找:
window.find();
<h2 id="8.2">8.2 location对象</h2>
location提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。
location既是window对象的属性,也是document对象的属性。
location将URL解析为独立的片段
<h3 id="8.2.1">8.2.1 查询字符串参数</h3>
以下函数解析查询字符串,然后返回包含所有参数的一个对象:
function getQueryStringArgs(){
var qs = location.search.length > 0 ? location.search.substring(1) : "";
var args = {};
var items = qs.length > 0 ? qs.split("&") : [];
var item = null;
var name = null;
var 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;
}
<h3 id="8.2.2">8.2.2 位置操作</h3>
以下三种方法本质上都是调用assign()方法,location.href比较常用
location.assign(URL);
window.location = URL;
location.href = URL;
通过改变location对象的其他属性值来改变当前加载的页面:
//假设初始URL为http://www.wrox.com/WileyCDA/
//http://www.wrox.com/WileyCDA/#section1
location.hash = "#section1";
//http://www.wrox.com/WileyCDA/?q=javascript
location.search = "?q=javascript";
//http://www.yahoo.com/WileyCDA/
location.hostname = "www.yahoo.com";
//http://www.wrox.com/mydir/
location.pathname = "mydir";
//http://www.wrox.com:8080/WileyCDA/
location.port = 8080;
每次修改location的属性(除hash),页面都会以新URL重新加载
replace()
方法:
作用:禁用后退按钮
-
示例:访问该网页的时候1s后导航到百度,并且后退按钮被禁用
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> setTimeout(function () { location.replace("http://www.baidu.com/"); },1000); </script> </body> </html>
reload()
方法:
location.reload();//重新加载(有可能从缓存中加载)
location.reload(true);//重新加载(从服务器重新加载)
- 位于reload()之后的代码可能不执行,取决于网络延迟或系统资源等因素,因此最好将reload()放在代码最后一行
<h2 id="8.3">8.3 navigator对象</h2>
navigator对象的属性通常用于检测显示网页的浏览器类型
<h3 id="8.3.1">8.3.1 检测插件</h3>
非IE:
-
方法:用plungins数组,plungins的每一项包含下列属性:
- name:插件名字
- description:插件描述
- filename:插件文件名
- length:插件所处理的MIME类型数量
具体:循环迭代每个插件并将插件的name与给定的名字比较
-
代码:
function hasPlungin(name){ name = name.toLowerCase(); for(var i=0;i<navigator.plungins.length;i++){ if(navagator.plungins[i].name.toLoowerCase().indexOf(name)>-1){ return true; } } return false; }
IE:
方法:使用专有的ActiveXObject类型
具体:传入的参数是一个COM标识符,通过尝试创建一个特定插件的实例来确定有没有插件
-
代码:
function hasIEPlungins(name){ try{ new ActiveXObject(name); return true; }catch (ex){ return false; } }
因此在所有浏览器中检测时要针对每个插件分别创建函数:
//检测所有浏览器中的Flash
function hasFlash(){
var result = hasPlungin("Flash");
if(!result){
result = hasIEPlungin("ShockwaveFlash.ShockwaveFlash");
}
return result;
}
<h3 id="8.3.2">8.3.2 注册处理程序</h3>
<h2 id="8.4">8.4 screen对象</h2>
用来表现客户端能力
<h2 id="8.5">8.5 history对象</h2>
用来保存历史记录
-
history.go()方法
- 参数:整数值(负数向后跳转,相当于后退)或字符串
- 当输入字符串时,会跳到最近的包含这个字符串的页面
- history.back():后退一页
- history.forward():前进一页
-
length属性
- 检测当前页面是不是用户打开的第一个页面
<h2 id="8.6">8.6 小结</h2>
- 在使用框架时,每个框架都有自己的window对象以及所有原生构造函数和其他函数的副本。每个框架都保存在frames集合中
- 有一些窗口指针,可以用来引用其他框架,包括父框架
- top对象始终指向最外围的框架
- parent对象指向包含当前框架的框架
- self对象回指window
- location对象可以通过编程方式来访问浏览器的导航系统
- 调用replace()方法可以导航到一个新的URL并替换历史记录种当前显示的页面
- navigator对象提供了与浏览器有关的信息
- screen对象保存着与客户端显示器有关的信息
- history对象保存着历史记录,包括后退和前进