BOM(浏览器对象模型)提供了不少对象,用于访问浏览器的功能。javascript
8.1 window 对象html
BOM 的核心对象是window,它表示浏览器的一个实例。在浏览器中,window 对象有双重角色,它既是经过JavaScript 访问浏览器窗口的一个接口,又是ECMAScript 规定的Global 对象。这意味着在网页中定义的任何一个对象、变量和函数,都以window 做为其Global 对象,所以有权访问parseInt()等方法。java
8.1.1 全局做用域数组
因为window 对象同时扮演着ECMAScript 中Global 对象的角色,所以全部在全局做用域中声明的变量、函数都会变成window 对象的属性和方法。浏览器
var age=29; function sayAge(){ console.log(this.age); } console.log(window.age);//29 sayAge();//29 window.sayAge();//29
咱们在全局做用域中定义了一个变量age 和一个函数sayAge(),它们被自动归在了window 对象名下。因而,能够经过window.age 访问变量age,能够经过window.sayAge()访问函数sayAge()。因为sayAge()存在于全局做用域中,所以this.age 被映射到window.age,最终显示的仍然是正确的结果。缓存
抛开全局变量会成为window 对象的属性不谈,定义全局变量与在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;
8.1.2 窗口关系及框架cookie
若是页面中包含框架,则每一个框架都拥有本身的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 对象指向的都是那个框架的特定实例,而非最高层的框架。
与top 相对的另外一个window 对象是parent。顾名思义,parent(父)对象始终指向当前框架的直接上层框架。在某些状况下,parent 有可能等于top;但在没有框架的状况下,parent 必定等于top(此时它们都等于window)。
与框架有关的最后一个对象是self,它始终指向window;实际上,self 和window 对象能够互换使用。引入self 对象的目的只是为了与top 和parent 对象对应起来,所以它不格外包含其余值。
8.1.3 窗口位置
用来肯定和修改window 对象位置的属性和方法有不少。
IE、Safari、Opera 和Chrome 都提供了screenLeft 和screenTop 属性,分别用于表示窗口相对于屏幕左边和上边的位置。
Firefox 则在screenX 和screenY 属性中提供相同的窗口位置信息,Safari 和Chrome 也同时支持这两个属性。
Opera虽然也支持screenX 和screenY 属性,但与screenLeft 和screenTop 属性并不对应,所以建议你们不要在Opera 中使用它们。
使用下列代码能够跨浏览器取得窗口左边和上边的位置。
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX; var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
这个例子运用二元操做符首先肯定screenLeft 和screenTop 属性是否存在,若是是(在IE、Safari、Opera 和Chrome 中),则取得这两个属性的值。若是不存在(在Firefox 中),则取得screenX和screenY 的值。
在IE、Opera 中,screenLeft 和screenTop 中保存的是从屏幕左边和上边到由window 对象表示的页面可见区域的距离。换句话说,若是window 对象是最外层对象,并且浏览器窗口紧贴屏幕最上端——即y 轴坐标为0,那么screenTop 的值就是位于页面可见区域上方的浏览器工具栏的像素高度。可是,在Chrome、Firefox 和Safari 中,screenY 或screenTop中保存的是整个浏览器窗口相对于屏幕的坐标值,即在窗口的y 轴坐标为0 时返回0。
使用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);
8.1.4 窗口大小
IE9+、Firefox、Safari、Opera 和Chrome 均为此提供了4 个属性:innerWidth、innerHeight、outerWidth 和outerHeight。
在IE9+、Safari 和Firefox中,outerWidth 和outerHeight 返回浏览器窗口自己的尺寸(不管是从最外层的window 对象仍是从
某个框架访问)。在Opera 中,这两个属性的值表示页面视图容器的大小。而innerWidth 和innerHeight则表示该容器中页面视图区的大小(减去边框宽度)。
在Chrome 中,outerWidth、outerHeight 与innerWidth、innerHeight 返回相同的值,即视口(viewport)大小而非浏览器窗口大小。
IE8 及更早版本没有提供取得当前浏览器窗口尺寸的属性;不过,它经过DOM 提供了页面可见区域的相关信息。
在IE、Firefox、Safari、Opera 和Chrome 中,document.documentElement.clientWidth 和document.documentElement.clientHeight 中保存了页面视口的信息。在IE6 中,这些属性必须在标准模式下才有效;若是是混杂模式,就必须经过document.body.clientWidth 和document.body.clientHeight 取得相同信息。而对于混杂模式下的Chrome,则不管经过document.documentElement仍是document.body 中的clientWidth 和clientHeight 属性,均可以取得视口的大小。
虽然最终没法肯定浏览器窗口自己的大小,但却能够取得页面视口的大小,以下
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.client-Width 和document.documentElement.clientHeihgt 提供了相同的信息。随着页面的缩放,这些值也会相应变化。
使用resizeTo()和resizeBy()方法能够调整浏览器窗口的大小。这两个方法都接收两个参数,其中resizeTo()接收浏览器窗口的新宽度和新高度,而resizeBy()接收新窗口与原窗口的宽度和高度之差。
//调整到100×100 window.resizeTo(100, 100); //调整到200×150 window.resizeBy(100, 50); //调整到 300×300 window.resizeTo(300, 300);
8.1.5 导航和打开窗口
使用window.open()方法既能够导航到一个特定的URL,也能够打开一个新的浏览器窗口。这个方法能够接收4 个参数:要加载的URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。一般只须传递第一个参数,最后一个参数只在不打开新窗口的状况下使用。
若是为window.open()传递了第二个参数,并且该参数是已有窗口或框架的名称,那么就会在具备该名称的窗口或框架中加载第一个参数指定的URL。
//等同于< a href="http://www.wrox.com" target="topFrame"></a> window.open("http://www.wrox.com/", "topFrame");
调用这行代码,就如同用户单击了href 属性为http://www.wrox.com/,target 属性为"topFrame"的连接。若是有一个名叫"topFrame"的窗口或者框架,就会在该窗口或框架加载这个URL;不然,就会建立一个新窗口并将其命名为"topFrame"。此外,第二个参数也能够是下列任何一个特殊的窗口名称:_self、_parent、_top 或_blank。
一、弹出窗口
若是给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");
window.open()方法会返回一个指向新窗口的引用。引用的对象与其余window 对象大体类似,但咱们能够对其进行更多控制。例如,有些浏览器在默认状况下可能不容许咱们针对主浏览器窗口调整大小或移动位置,但却容许咱们针对经过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();
对于浏览器的主窗口,若是没有获得用户的容许是不能关闭它的。不过,弹出窗口却是能够调用top.close()在不经用户容许的状况下关闭本身。弹出窗口关闭以后,窗口的引用仍然还在,但除了像下面这样检测其closed 属性以外,已经没有其余用处了。
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 就是告诉浏览器新建立的标签页不须要与打开它的标签页通讯,所以能够在独立的进程中运行。标签页之间的联系一旦切断,将没有办法恢复。
2. 安全限制
Windows XP SP2 中的IE6 对弹出窗口施加了多方面的安全限制,包括不容许在屏幕以外建立弹出窗口、不容许将弹出窗口移动到屏幕之外、不容许关闭状态栏等。IE7 则增长了更多的安全限制,如不容许关闭地址栏、默认状况下不容许移动弹出窗口或调整其大小。Firefox 1 从一开始就不支持修改状态栏,所以不管给window.open()传入什么样的特性字符串,弹出窗口中都会无一例外地显示状态栏。后来的Firefox 3 又强制始终在弹出窗口中显示地址栏。Opera 只会在主浏览器窗口中打开弹出窗口,但不容许它们出如今可能与系统对话框混淆的地方。
此外,有的浏览器只根据用户操做来建立弹出窗口。这样一来,在页面还没有加载完成时调用window.open()的语句根本不会执行,并且还可能会将错误消息显示给用户。换句话说,只能经过单击或者击键来打开弹出窗口。
对于那些不是用户有意打开的弹出窗口,Chrome 采起了不一样的处理方式。它不会像其余浏览器那样简单地屏蔽这些弹出窗口,而是只显示它们的标题栏,并把它们放在浏览器窗口的右下角。
3. 弹出窗口屏蔽程序
大多数浏览器都内置有弹出窗口屏蔽程序,而没有内置此类程序的浏览器,也能够安装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!"); }
在任何状况下,以上代码均可以检测出调用window.open()打开的弹出窗口是否是被屏蔽了。但要注意的是,检测弹出窗口是否被屏蔽只是一方面,它并不会阻止浏览器显示与被屏蔽的弹出窗口有关的消息。
8.1.6 间歇调用和超时调用
JavaScript 是单线程语言,但它容许经过设置超时值和间歇时间值来调度代码在特定的时刻执行。前者是在指定的时间事后执行代码,然后者则是每隔指定的时间就执行一次代码。
超时调用须要使用window 对象的setTimeout()方法,它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前须要等待多少毫秒)。其中,第一个参数能够是一个包含JavaScript 代码的字符串(就和在eval()函数中使用的字符串同样),也能够是一个函数。
例如,下面对setTimeout()的两次调用都会在一秒钟后显示一个警告框。
//不建议传递字符串! 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);
只要是在指定的时间还没有过去以前调用clearTimeout(),就能够彻底取消超时调用。前面的代码在设置超时调用以后立刻又调用了clearTimeout(),结果就跟什么也没有发生同样。
超时调用的代码都是在全局做用域中执行的,所以函数中this 的值在非严格模式下指向window 对象,在严格模式下是undefined。
间歇调用与超时调用相似,只不过它会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载。设置间歇调用的方法是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);
在这个例子中,变量num 每半秒钟递增一次,当递增到最大值时就会取消先前设定的间歇调用。这个模式也可使用超时调用来实现
var num = 0; var max = 10; function incrementNumber() { num++; //若是执行次数未达到max 设定的值,则设置另外一次超时调用 if (num < max) { setTimeout(incrementNumber, 500); } else { alert("Done"); } } setTimeout(incrementNumber, 500);
可见,在使用超时调用时,没有必要跟踪超时调用ID,由于每次执行代码以后,若是再也不设置另外一次超时调用,调用就会自行中止。通常认为,使用超时调用来模拟间歇调用的是一种最佳模式。
8.1.7 系统对话框
浏览器经过alert()、confirm()和prompt()方法能够调用系统对话框向用户显示消息。系统对话框与在浏览器中显示的网页没有关系,也不包含HTML。它们的外观由操做系统及(或)浏览器设置决定,而不是由CSS 决定。此外,经过这几个方法打开的对话框都是同步和模态的。也就是说,显示这些对话框的时候代码会中止执行,而关掉这些对话框后代码又会恢复执行。
alert()方法,这个方法接受一个字符串并将其显示给用户。具体来讲,调用alert()方法的结果就是向用户显示一个系统对话框,其中包含指定的文本和一个OK(“肯定”)按钮。
alert("Hello world!");
第二种对话框是调用confirm()方法生成的。从向用户显示消息的方面来看,这种“确认”对话框很像是一个“警告”对话框。但两者的主要区别在于“确认”对话框除了显示OK 按钮外,还会显示一个Cancel(“取消”)按钮,两个按钮可让用户决定是否执行给定的操做。
confirm("Are yous ure?");
为了肯定用户是单击了OK 仍是Cancel,能够检查confirm()方法返回的布尔值:true 表示单击了OK,false 表示单击了Cancel 或单击了右上角的X 按钮。确认对话框的典型用法以下。
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()方法生成的,这是一个“提示”框,用于提示用户输入一些文本。提示框中除了显示OK 和Cancel 按钮以外,还会显示一个文本输入域,以供用户在其中输入内容。prompt()方法接受两个参数:要显示给用户的文本提示和文本输入域的默认值(能够是一个空字符串)。
prompt("What's your name?","Michael");
若是用户单击了OK 按钮,则prompt()返回文本输入域的值;若是用户单击了Cancel 或没有单击OK 而是经过其余方式关闭了对话框,则该方法返回null。
var result = prompt("What is your name? ", ""); if (result !== null) { alert("Welcome, " + result); }
还有两个能够经过JavaScript 打开的对话框,即“查找”和“打印”。这两个对话框都是异步显示的,可以将控制权当即交还给脚本。这两个对话框与用户经过浏览器菜单的“查找”和“打印”命令打开的对话框相同。而在JavaScript 中则能够像下面这样经过window 对象的find()和print()方法打开它们。
//显示“打印”对话框 window.print(); //显示“查找”对话框 window.find();
8.2 location 对象
location 是最有用的BOM对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。事实上,location 对象是很特别的一个对象,由于它既是window 对象的属性,也是document 对象的属性;换句话说,window.location 和document.location 引用的是同一个对象。location 对象的用处不仅表如今它保存着当前文档的信息,还表如今它将URL 解析为独立的片断,让开发人员能够经过不一样的属性访问这些片断。下表列出了location 对象的全部属性。
属性名 | 例子 | 说明 |
hash | "#contents" | 返回URL中的hash(#号后跟零或多个字符),若是URL中不包含散列,则返回空字符串 |
host | "www.360.com:80" | 返回服务器名称和端口号(若是有) |
hostname | "www.360.com" | 返回不带端口号的服务器名称 |
href | "http://www.360.com" | 返回当前加载页面的完整URL。而location对象的toString()方法也返回这个值 |
pathname | "/wileyCDA/" | 返回URL中的目录和(或文件名) |
port | "8080" | 返回URL中指定的端口号。若是URL中不包含端口号,则这个属性返回空字符串 |
protocol | "http" | 返回页面使用的协议。一般是http:或https: |
search | "?q=javascript" | 返回URL的查询字符串。这个字符串以问号开头 |
8.2.1 查询字符串参数
虽然经过上面的属性能够访问到location 对象的大多数信息,但其中访问URL 包含的查询字符串的属性并不方便。尽管location.search 返回从问号到URL 末尾的全部内容,但却没有办法逐个访问其中的每一个查询字符串参数。为此,能够像下面这样建立一个函数,用以解析查询字符串,而后返回包含全部参数的一个对象:
function getQueryStringArgs(){ //取得查询字符串并去掉开头的问号 var qs = (location.search.length > 0 ? location.search.substring(1) : ""), //保存数据的对象 args = {}, //取得每一项 items = qs.length ? qs.split("&") : [], item = null, name = null, value = null, //在for 循环中使用 i = 0, len = items.length; //逐个将每一项添加到args 对象中 for (i=0; i < len; i++){ item = items[i].split("="); name = decodeURIComponent(item[0]); value = decodeURIComponent(item[1]); if (name.length) { args[name] = value; } } return args; }
下面给出了使用这个函数的示例。
//假设查询字符串是?q=javascript&num=10 var args = getQueryStringArgs(); alert(args["q"]); //"javascript" alert(args["num"]); //"10"
可见,每一个查询字符串参数都成了返回对象的属性。这样就极大地方便了对每一个参数的访问。
8.2.2 位置操做
使用location 对象能够经过不少方式来改变浏览器的位置。首先,也是最经常使用的方式,就是使用assign()方法并为其传递一个URL,以下所示。
location.assign("http://www.wrox.com");
这样,就能够当即打开新URL 并在浏览器的历史记录中生成一条记录。若是是将location.href或window.location 设置为一个URL 值,也会以该值调用assign()方法。例如,下列两行代码与显式调用assign()方法的效果彻底同样。
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
在这些改变浏览器位置的方法中,最经常使用的是设置location.href 属性。
另外,修改location 对象的其余属性也能够改变当前加载的页面。下面的例子展现了经过将hash、search、hostname、pathname 和port 属性设置为新值来改变URL。
//假设初始URL 为http://www.wrox.com/WileyCDA/ //将URL 修改成"http://www.wrox.com/WileyCDA/#section1" location.hash = "#section1"; //将URL 修改成"http://www.wrox.com/WileyCDA/?q=javascript" location.search = "?q=javascript"; //将URL 修改成"http://www.yahoo.com/WileyCDA/" location.hostname = "www.yahoo.com"; //将URL 修改成"http://www.yahoo.com/mydir/" location.pathname = "mydir"; //将URL 修改成"http://www.yahoo.com:8080/WileyCDA/" location.port = 8080;
每次修改location 的属性(hash 除外),页面都会以新URL 从新加载。
当经过上述任何一种方式修改URL 以后,浏览器的历史记录中就会生成一条新记录,所以用户经过单击“后退”按钮都会导航到前一个页面。要禁用这种行为,可使用replace()方法。这个方法只接受一个参数,即要导航到的URL;结果虽然会致使浏览器位置改变,但不会在历史记录中生成新记录。在调用replace()方法以后,用户不能回到前一个页面,来看下面的例子:
<!DOCTYPE html> <html> <head> <title>You won't be able to get back here</title> </head> <body> <p>Enjoy this page for a second, because you won't be coming back here.</p> <script type="text/javascript"> setTimeout(function () { location.replace("http://www.wrox.com/"); }, 1000); </script> </body> </html>
若是将这个页面加载到浏览器中,浏览器就会在1 秒钟后从新定向到www.wrox.com。而后,“后退”按钮将处于禁用状态,若是不从新输入完整的URL,则没法返回示例页面。
与位置有关的最后一个方法是reload(),做用是从新加载当前显示的页面。若是调用reload()时不传递任何参数,页面就会以最有效的方式从新加载。也就是说,若是页面自上次请求以来并无改变过,页面就会从浏览器缓存中从新加载。若是要强制从服务器从新加载,则须要像下面这样为该方法传递参数true。
location.reload(); //从新加载(有可能从缓存中加载) location.reload(true); //从新加载(从服务器从新加载)
位于reload()调用以后的代码可能会也可能不会执行,这要取决于网络延迟或系统资源等因素。为此,最好将reload()放在代码的最后一行。
8.3 navigatior 对象
与其余BOM 对象的状况同样,每一个浏览器中的navigator 对象也都有一套本身的属性。下表列出了存在于全部浏览器中的属性和方法,以及支持它们的浏览器版本。
属性或方法 | 说明 | IE | Firefox | Safari/Chrome |
Opera |
appCodeName | 浏览器的名称。一般都是Mozilla,即 使在非Mozilla浏览器中也是如此 |
3.0+ | 1.0+ | 1.0+ | 7.0+ |
appMinorVersion | 次版本信息 | 4.0+ | - | - | 9.5+ |
appName | 完整的浏览器名称 | 3.0+ | 1.0+ | 1.0+ | 7.0+ |
appVersion | 浏览器的版本。通常不与实际的浏览器 版本对应 |
3.0+ | 1.0+ | 1.0+ | 7.0+ |
buildID | 浏览器编译版本 | - | 2.0+ | - | - |
cookieEnabled | 表示cookie是否启用 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
cpuClass | 客户端计算机中使用的CPU类型(x8六、 68K、Alpha、PPC或Other) |
4.0+ | - | - | - |
javaEnabled() | 表示当前浏览器中是否启用了Java | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
language | 浏览器的主语言 | - | 1.0+ | 1.0+ | 7.0+ |
mimeTypes | 在浏览器中注册的MIME类型数组 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
onLine | 表示浏览器是否链接到了因特网 | 4.0+ | 1.0+ | - | 9.5+ |
opsProfile | 彷佛早就不用了。查不到相关文档 | 4.0+ | - | - | - |
oscpu | 客户端计算机的操做系统或使用的CPU | - | 1.0+ | - | - |
platform | 浏览器所在的系统平台 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
plugins | 浏览器中安装的插件信息的数组 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
preference() | 设置用户的首选项 | - | 1.5+ | - | - |
product | 产品名称(如 Gecko) | - | 1.0+ | 1.0+ | - |
productSub | 关于产品的次要信息(如Gecko的版本) | - | 1.0+ | 1.0+ | - |
register-ContentHandler() | 针对特定的MIME类型将一个站点注册 为处理程序 |
- | 2.0+ | - | - |
register-ProtocolHandler() | 针对特定的协议将一个站点注册为处 理程序 |
- | 2.0+ | - | - |
securityPolicy | 已经废弃。安全策略的名称。为了与 Netscape Navigator 4向后兼容而保留下来 |
- | 1.0+ | - | - |
systemLanguage | 操做系统的语言 | 4.0+ | - | - | - |
taintEnabled() | 已经废弃。表示是否容许变量被修改(taint)。为了 |
4.0+ | 1.0+ | - | 7.0+ |
userAgent | 浏览器的用户代理字符串 | 3.0+ | 1.0+ | 1.0+ | 7.0+ |
userLanguage | 操做系统的默认语言 | 4.0+ | - | - | 7.0+ |
userProfile | 借以访问用户我的信息的对象 | 4.0+ | - | - | - |
vendor | 浏览器的品牌 | - | 1.0+ | 1.0+ | - |
vendorSub | 有关供应商的次要信息 | - | 1.0+ | 1.0+ | - |
表中的这些navigator 对象的属性一般用于检测显示网页的浏览器类型
8.3.1 检测插件
检测浏览器中是否安装了特定的插件是一种最多见的检测例程。对于非IE 浏览器,可使用plugins 数组来达到这个目的。该数组中的每一项都包含下列属性。
通常来讲,name 属性中会包含检测插件必需的全部信息,但有时候也不彻底如此。在检测插件时,须要像下面这样循环迭代每一个插件并将插件的name 与给定的名字进行比较。
//检测插件(在IE 中无效) function hasPlugin(name){ name = name.toLowerCase(); for (var i=0; i < navigator.plugins.length; i++){ if (navigator. plugins [i].name.toLowerCase().indexOf(name) > -1){ return true; } } return false; } //检测Flash alert(hasPlugin("Flash")); //检测QuickTime alert(hasPlugin("QuickTime"));
这个hasPlugin()函数接受一个参数:要检测的插件名。第一步是将传入的名称转换为小写形式,以便于比较。而后,迭代plugins 数组,经过indexOf()检测每一个name 属性,以肯定传入的名称是否出如今字符串的某个地方。比较的字符串都使用小写形式能够避免因大小写不一致致使的错误。而传入的参数应该尽量具体,以免混淆。应该说,像Flash 和QuickTime 这样的字符串就比较具体了,不容易致使混淆。
检测IE 中的插件比较麻烦,由于IE 不支持Netscape 式的插件。在IE 中检测插件的惟一方式就是使用专有的ActiveXObject 类型,并尝试建立一个特定插件的实例。IE 是以COM对象的方式实现插件的,而COM对象使用惟一标识符来标识。所以,要想检查特定的插件,就必须知道其COM标识符。
//检测IE 中的插件 function hasIEPlugin(name){ try { new ActiveXObject(name); return true; } catch (ex){ return false; } } //检测Flash alert(hasIEPlugin("ShockwaveFlash.ShockwaveFlash")); //检测QuickTime alert(hasIEPlugin("QuickTime.QuickTime"));
在这个例子中,函数hasIEPlugin()只接收一个COM 标识符做为参数
鉴于检测这两种插件的方法差异太大,所以典型的作法是针对每一个插件分别建立检测函数,而不是使用前面介绍的通用检测方法。
//检测全部浏览器中的Flash function hasFlash(){ var result = hasPlugin("Flash"); if (!result){ result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash"); } return result; } //检测全部浏览器中的QuickTime function hasQuickTime(){ var result = hasPlugin("QuickTime"); if (!result){ result = hasIEPlugin("QuickTime.QuickTime"); } return result; } //检测Flash alert(hasFlash()); //检测QuickTime alert(hasQuickTime());
上面代码中定义了两个函数:hasFlash()和hasQuickTime()。每一个函数都是先尝试使用不针对IE 的插件检测方法。若是返回了false(在IE 中会这样),那么再使用针对IE 的插件检测方法。若是IE 的插件检测方法再返回false,则整个方法也将返回false。只要任何一次检测返回true,整个方法都会返回true。
8.3.2 注册处理程序
Firefox 2 为navigator 对象新增了registerContentHandler()和registerProtocolHandler()方法。这两个方法可让一个站点指明它能够处理特定类型的信息。随着RSS 阅读器和在线电子邮件程序的兴起,注册处理程序就为像使用桌面应用程序同样默认使用这些在线应用程序提供了一种方式。
其中,registerContentHandler()方法接收三个参数:要处理的MIME 类型、能够处理该MIME类型的页面的URL 以及应用程序的名称。举个例子,要将一个站点注册为处理RSS 源的处理程序,可使用以下代码。
navigator.registerContentHandler("application/rss+xml","http://www.somereader.com?feed=%s", "Some Reader");
第一个参数是RSS 源的MIME 类型。第二个参数是应该接收RSS 源URL 的URL,其中的%s 表示RSS 源URL,由浏览器自动插入。当下一次请求RSS 源时,浏览器就会打开指定的URL,而相应的Web 应用程序将以适当方式来处理该请求。
相似的调用方式也适用于registerProtocolHandler()方法,它也接收三个参数:要处理的协议(例如,mailto 或ftp)、处理该协议的页面的URL 和应用程序的名称。例如,要想将一个应用程序注册为默认的邮件客户端,可使用以下代码。
navigator.registerProtocolHandler("mailto","http://www.somemailclient.com?cmd=%s", "Some Mail Client");
这个例子注册了一个mailto 协议的处理程序,该程序指向一个基于Web 的电子邮件客户端。一样,第二个参数仍然是处理相应请求的URL,而%s 则表示原始的请求。
8.4 screen对象
screen 对象基本上只用来代表客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等。每一个浏览器中的screen 对象都包含着各不相同的属性,下表列出了全部属性及支持相应属性的浏览器。
这些信息常常集中出如今测定客户端能力的站点跟踪工具中,但一般不会用于影响功能。不过,有时候也可能会用到其中的信息来调整浏览器窗口大小,使其占据屏幕的可用空间,例如:
window.resizeTo(screen.availWidth, screen.availHeight);
8.5 history 对象
history 对象保存着用户上网的历史记录,从窗口被打开的那一刻算起。由于history 是window对象的属性,所以每一个浏览器窗口、每一个标签页乃至每一个框架,都有本身的history 对象与特定的window 对象关联。出于安全方面的考虑,开发人员没法得知用户浏览过的URL。不过,借由用户访问过的页面列表,一样能够在不知道实际URL 的状况下实现后退和前进。
使用go()方法能够在用户的历史记录中任意跳转,能够向后也能够向前。这个方法接受一个参数,表示向后或向前跳转的页面数的一个整数值。负数表示向后跳转(相似于单击浏览器的“后退”按钮),正数表示向前跳转(相似于单击浏览器的“前进”按钮)。来看下面的例子。
//后退一页 history.go(-1); //前进一页 history.go(1); //前进两页 history.go(2);
也能够给go()方法传递一个字符串参数,此时浏览器会跳转到历史记录中包含该字符串的第一个位置——可能后退,也可能前进,具体要看哪一个位置最近。若是历史记录中不包含该字符串,那么这个方法什么也不作,例如:
//跳转到最近的wrox.com 页面 history.go("wrox.com"); //跳转到最近的nczonline.net 页面 history.go("nczonline.net");
另外,还可使用两个简写方法back()和forward()来代替go()。顾名思义,这两个方法能够模仿浏览器的“后退”和“前进”按钮。
//后退一页 history.back(); //前进一页 history.forward();
除了上述几个方法外,history 对象还有一个length 属性,保存着历史记录的数量。这个数量包括全部历史记录,即全部向后和向前的记录。对于加载到窗口、标签页或框架中的第一个页面而言,history.length 等于0。经过像下面这样测试该属性的值,能够肯定用户是否一开始就打开了你的页面。
if (history.length == 0){ //这应该是用户打开窗口后的第一个页面 }