您的位置:首页 > 其它

BOM(浏览器对象模型)

2013-03-15 13:58 225 查看
ECMAScript 是JavaScript的核心,但如果要在Web中使用JavaScript,那么BOM(浏览器对象模型)则无疑才是真正的核心。

BOM提供了很多对象,用于访问浏览器的功能,这些功能与任何网页内容无关。缺少事实上的规范导致BOM即有意思,又有问题,因为浏览器提供商会按照各自的想法随意去扩展它。于是,浏览器之间公有的对象,就成了事实上的标准。

一、window对象

BOM的核心对象是window,它表示浏览器的一个实例。

在浏览器中,window对象有双重角色,它既是通过JavaScript访问浏览器窗口的一个借口,又是ECMAScript规定的 Global 对象。

这意味着在网页中定义的任何一个对象、变量和函数,都以 window 作为其 Global 对象,因此有权访问 parseInt() 等方法。

1)全局作用域
由于 window 对象同时扮演着 ECMAScript 中 Global 对象的角色,因此所有在全局作用域中声明的变量、函数都会变成 window 对象的属性和方法。

2)窗口关系及框架
如果页面中包含框架,则每个框架都拥有自己的 window 对象,并且保存在 frames 集合中。在 frames 集合中,可以通过数值索引(从0开始,从左至右,从上到下)或者框架名称来访问相应的 window 对象。每个 window 对象都有一个 name 属性,其中包含框架的名称。

可以使用 window.frames[0] 或者 window.frames["frameName"] 来引用框架。不过最好使用 top 而非 window 来引用这些框架(例如,top.frames[0])。

top 始终指向最高(最外)层的框架,也就是浏览器窗口。使用它可以确保在一个框架中正确的访问另一个框架。因为对于在一个框架中编写的任何代码来说,其中的 window 对象指向的都是那个框架的特定实例,而非最高层的框架。

与 top 相对的另一个 window 对象是 parent。顾名思义 parent 对象始终指向当前框架的直接上层框架。但在没有框架的情况下,parent 一定等于 top (此时他们都等于 window )。

注意:除非最高层窗口是通过 window.open() 打开的,否则其 window 对象的 name 属性不会包含任何值。

与框架有关的最后一个对象是 self ,它始终指向 window ;事实上,self 和 window 对象可以互换使用。引入 self 对象的目的只是为了与 top 和 parent 对象对应起来。

3)窗口位置
IE、Safari、Opera 和 Chrome 都提供了 screenLeft 和 screenTop 属性,分别用于表示窗口相对于屏幕左边和上边的位置。 Firefox 则 在 screenX 和 screenY 属相中提供相同的窗口位置信息。Safari 和 Chrome也同时支持这两个属性。 Opera 虽然也支持 screenX 和 screenY 属性,但与 screenLeft 和 screenTop 属性并不对应。

使用如下代码可以跨浏览器获取窗口左边和上边的位置:

var leftPos = ( typeof window.screenLeft == "number" ) ? window.screenLeft : window.screenX;

var topPos = ( typeof window.screenTop == "number") ? window.screenTop : window.screenY;


IE、Opera 和 Chrome 中,screenLeft 和 screenTop 中保存的是从屏幕左边和上边到由 window 对象表示的页面可见区域的距离。在 Firefox 和 Safari 中, screenTop就是保存的整个浏览器窗口相对于屏幕的坐标值。

因此,无法跨浏览器去的窗口左边和上边的精确坐标。然而,使用 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(以及更高版本)中默认是禁用的。另外,这两个方法都不适用于框架,只能对最外层的 window 对象使用。

4)窗口大小

跨浏览器确定一个窗口的大小不是一件简单的事。

Firefox、Safari、Opera 和 Chrome 均为此提供了 4 个属性:innerWidth、innerHeight、outerWidth 和 outerHeight。

在 Safari 和 Firefox 中,outWidth 和 outerHeight 返回浏览器窗口本身的尺寸(无论是从最外层的 window 对象还是从某个框架访问。

在 Opera 中,这两个属性的值表示页面视图容器(值 Oprea 中单个标签页对应的浏览器窗口)的大小。
而 innerWidth 和 innerHeight 则表示该容器中页面视图区的大小(减去边框宽度)。

在 Chrome 中,outerWidth、outerHeight 与 innerWidth、innerHeight 返回相同的值,即适口(viewport)大小而非浏览器窗口大小。

IE 没有提供去的当前浏览器窗口尺寸的属性;不过,它通过 DOM 提供了页面可见区域的相关信息。

在 IE 以及 Firefox、Safari、Opera 和 Chrome 中,document.documentElement.clientHeight 和 document.documentElement.clientWidth 中保存了页面视口的信息。

在 IE6 下,这些属性必须在标准模式下才有效。如果是混杂模式,就必须通过 document.body.clientWidth 和 document.body.clientHeight 取得相同信息。

而对于混杂模式下的 Chrome ,则都可以取得视口大小。

最终无法确定浏览器窗口本身的大小,但却可以获得页面视口的大小。

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;
}
}

resizeTo() 接受两个参数,浏览器窗口的新宽度和新高度。
resizeBy() 接受两个参数,新窗口与原窗口的宽度和高度的差。

//调整到 100 × 100
window.resizeTo(100, 100);

//调整到 200 × 150
window.resizeBy(100, 50);

//调整到 300 ×  300
window.resizeTo(300, 300);


注意:这两个方法也有可能会被浏览器禁用。在Opera 和 IE7(以及更高版本)中默认是禁用的。另外,这两个方法都不适用于框架,只能对最外层的 window 对象使用。

5)导航和打开窗口
使用 window.open() 方法既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。这个方法接收四个参数:需要加载的URL、目标窗口、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。

第二个参数除了自己的命名外,还可以是下列任何一个特殊的窗口名称:_self、_parent、_top 和 _blank。

①、弹出窗口
如果给 window.open() 传递的第二个参数不是一个已存在的窗口或框架,那么该方法会根据在第三个位置上传入的字符串创建一个新窗口或新标签页(根据浏览器的设置)。而在不打开新窗口的情况下会忽略第三个参数。

第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。

**************图片 a1******************************************

表中所列的部分或全部设置选项,都可以通过逗号分隔的名值对列表来指定。其中名值以等号表示(注意,整个特性字符串中不允许出现空格)

window.open() 方法会返回一个指向新窗口的引用。引用的对象与其他 window 对象大致相似,但我们可以对其进行更多的设置。例如,有些浏览器默认情况下会禁止我们条件窗口大小和移动位置,但通过 window.open() 创建的窗口则可以。

弹出的窗口可以调用 top.close() 在不经用户允许的情况下关闭自己。

新创建的 window 对象有一个 opener 属性,其中保存着打开它的原始窗口对象。这个属性只在弹出窗口中的最外层 window 对象( top )中定义,而且指向调用 window.open() 的窗口或框架。

虽然弹出窗口中有一个指针指向打开它的窗口,但原始窗口中并没有这样的指针指向弹出窗口。窗口并不跟踪记录它打开的弹出窗口,因此我们只在需要的时候手动实现跟踪。

有些浏览器(如 IE8 和 Chrome)会再独立的进程中运行每个标签页。当一个标签页打开另一个标签页时,如果两个 window 对象之间需要彼此通信,那么新标签页就不能运行在独立的进程中。在 Chrome 中,将新创建的标签页的 opener 属性设置为 null,即表示在单独的进程中运行标签页。

将 opener 属性设置为 null 就是告诉浏览器新创建的标签页不需要与打开它的标签页通信,因此可以在独立的进程中运行。标签页之间的联系一旦切断,就无法恢复。

②、安全限制
在打开计算机硬盘中的网页时,IE 会解除对弹出窗口的某些限制,但是在服务器上执行的这些代码会受到对弹出窗口的限制。

③、弹出窗口屏蔽程序

6)间歇调用和超时调用
JavaScript是单线程语言,但它允许通过设置超时值和间歇时间值来调度代码在特定的时刻执行。前者是指在指定的时间过后执行代码,而后者则是每隔指定的时间执行一次代码。

超时调用
需要使用 window 对象的 setTimeout() 方法,它接受两个参数:要执行的代码和以毫秒表示的时间。
其中第一个参数可以是一个包含 JavaScript 代码的字符串(就和在 eval() 函数中使用的字符串一样),也可以是一个函数。

//不建议传递字符串
setTimeout("alert('Hello world!')", 1000);

//推荐的调用方式
setTimeout(function(){
alert("Hello world!");
}, 1000);


虽然两种调用都没有问题,但由于传递字符串可能导致性能损失,因此不建议以字符串作为第一个参数。

调用 setTimeout() 之后,该方法会返回一个数值 ID,表示超时调用。这个超时调用 ID 是计划执行代码的唯一标识符,可以通过它来取消超时调用。

要取消未执行的超时调用计划,可以调用 clearTimeout() 方法并将相应的超时调用 ID 作为参数传递给它。

//设置超时调用
var timeoutId = setTimeout(function(){
alert("Hello world");
}, 1000);

//注意:把它取消
clearTimeout(timeoutId);


只要是在指定的时间尚未过去之前调用 clearTimeout(),就可以完全取消超时调用。

超时调用的代码都是在全局作用域中执行的,因此函数中 this 的值通常会指向 window 对象。

间歇调用
间歇调用与超时调用类似,只不过它会按照指定的时间间隔重复执行代码,直至间歇调用被取消或者页面被卸载。

设置间歇调用的方法是 setInterval() ,它接受的参数与 setTimeout() 相同。

//不建议传递字符串
setInterval("alert('Hello world!')", 1000);

//推荐的调用方式
setInterval(function(){
alert("Hello world!");
}, 1000);


调用 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 );


使用超时调用来模仿间歇调用是一种最佳模式。在开发环境下,很少使用真正的间歇调用,因为后一个间歇调用可能会在前一个间歇调用结束之前启动。而使用超时调用来模拟间歇调用则完全可以避免这一点。

var num = 0;
var max = 10;

function incrementNumber() {

num ++;

//如果执行次数未达到 max 设定的值,则设置另一次超时调用。
if( num < max ){
setTimeout( incrementNumber, 500 );
} else {
alert("Dome");
}
}

setTimeout( incrementNuber, 500 );


二、location 对象
location 是最有用的 BOM 对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。

location 对象是很特别的一个对象,因为它既是 window 对象的属性,也是 document 对象的属性。换句话说, window.location 和 document.location 引用的是同一个对象。location 对象的用处不只表现在它保存着当前文档的信息,还表现在它将 URL 解析为独立的片段,让开发人员可以通过不同的属性访问这些片段。

/************************ imga************************************************

1)查询字符串参数
虽然通过上面的属性可以访问到location对象的大多数信息,但其中访问URL包含的查询字符串的属性并不方便。尽管location.search 返回从问号到URL末尾的所有内容,但却没有办法逐个访问其中的每个查询字符串参数。为此可以像下面这样创建一个函数,用以解析查询字符串。然后返回保护焊所有参数的一个对象:

function getQueryStringArgs(){
//取得查询字符串,并去掉开头的问号
var qs = (location.search.length > 0 ? location.search.substring(1) : "" );

//保存数据的对象
var args = {};

//取得每一个项目
var items = qs.split("&");
var item = null;
var name = null;
var value = null;

//逐个将每一项添加到args对象中
for( var i = 0; i < items.length; i++){
item = items[i].split("=");
name = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
args[name] = value;
}
return args;
}

//访问示例
// ?q=javascript&num=10
var args = getQueryStringArgs();

alert(args["q"]);        //javascript
alert(args["num"]);                //10


2)位置操作
使用location对象昂可以通过很多方式来改变浏览器的位置。首先,也就是最常用的方式,就是使用assign()方法并Weiqin传递一个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对象的其他属性也可以改变当前加载的页面。

//假设初始URL为 http://www.wrox.com/WilerCDA 
//将URL修改为 http://www.wrox.com/WileyCDA/#sectiono1 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.wrox.com/mydir/ location.pathname = "mydir";

//将URL修改为 http://www.wrox.com:8080/WileyCDA/ location.port = 8080;


每次修改的属性( hash除外),页面都回以新的URL重新加载。

注意: 在IE8、Firefox 1、Safari 2、Opear 9 和 Chrome 0.2 中,修改hash的值会在浏览器的历史记录中生成一条记录。在IE的早期版本中,hash属性不会在用户单机“后退”和“前进”按钮时被更新,而只会在用户单击包含hash的URL时才会被更新。

replace() 函数
当通过上述的任何一种方式修改URL之后,浏览器的历史记录中就会生成一条新的记录,因此用户通过单击“后退”按钮就会导航到前一个页面。要禁用这种行为,可以使用replace()方法。

这个方法只接受一个采纳书,即要导航到的URL,结果虽然会导致浏览器位置改变,但不会在历史记录中生成新记录。调用replace()方法之后,用户不能回到前一个页面。

reload()函数
reload()函数作用是重新加载当前显示的页面。如果调用reload()时不传递任何参数,页面就会以最有效的方式重新加载。也就是说,如果页面自上次请求以来并没有改变过,页面就会从浏览器缓存中重新加载。如果需要强制从服务器重新加载,则需要像下面这一来传递参数:

location.reload(); //重新加载(可能从缓存中加载)
location.reload(true); //重新加载(从服务器加载)

主要:位于 reload() 调用后的代码可能会也可能不会执行,这要取决于网络延迟或系统资源等因素,因此最好将 relaod() 放在代码的最后一样。

三、navigator 对象
最早由 Netscape Navigator 2.0 引入的 navigator 对象,现在已经成为标识客户端浏览器的事实标准。

虽然其他浏览器也通过其他方式提供了相同或相似的信息(例如 IE中的 window.clientInformation 和 Opera 中的 window.opera),但navigator 对象却是所有支持 JavaScript 的浏览器所共同支持的。

与其他 BOM 对象的情况一样,每个浏览器中的navigator对象都会有一套自己的属性。

/********************** image **************************************

1)检测插件
检测浏览器中是否安装了特定的插件,对于非IE浏览器,可以使用 plugins 数组来达到这个目的。该数组包含下列属性:

name : 插件的名字;
description : 插件的描述;
filename : 插件的文件名
length : 插件所处理的 MIME类型数量

一般来说,name 属性中会包含检测插件所必须的所有信息,但有时候也不完全如此。在检测插件时,需要循环迭代每个插件并将插件的name 与给定的名字进行比较。

每个插件对象本身也是一个 MimeType 对象的数组,这些对象可以通过方括号语法来访问。每个 MimeType 对象有 4 个属性:包含MIME 类型描述的 description、回指插件对象的 enabledPlugin、标识与 MIME 类型对应的文件扩展名的字符串 suffixes (以都好分割)和标识完整 MIME 类型字符串的 type。

检测 IE 中的插件比较麻烦,因为 IE 不支持 Netscape 式的插件。在 IE 中检测插件的唯一方式就是使用专有的 ActiveXObject 类型,并尝试创建一个特定插件的实例。IE 是以 COM 对象的方式实现插件的,而 COM 对象使用唯一标识符来标识。

因此,想要检查特定的插件,就必须知道其 COM 标识符。

//检测所有浏览器插件的方法
function hashPlugin(name){    //非IE
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;
}

function hasIEPlugin(name){ //IE
tru{
new ActiveXObject(name);
return true;
}catch(ex){
return false;
}
}


plugins 集合有一个名为 refresh() 的方法,用于刷新 plugins 以反映最新安装的插件。这个方法接受一个参数: 标识似乎否应该重新加载页面的一个布尔值。如果这个值设置为true,则会重新加载包含插件的所有页面;否则,只更新 plugins 集合,不重新加载页面。

2)注册处理程序
Firefox 2.0 为 navigator 对象新增了 registerContentHandler() 和 reigsterProtocolHander() 方法,这两个方法在HTML5中定义的。

这两个方法可以让一个站点指明它可以处理特定类型的信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: