说说 JavaScript 中 BOM 的 window 对象

来源:互联网 发布:淘宝达人大v认证入口 编辑:程序博客网 时间:2024/06/04 19:13

BOM 的核心对象是 window,它是浏览器的一个实例。它既是 JavaScript 访问浏览器窗口的接口,又是 ECMAScript 规定的 Global 对象。

1 全局作用域

因为 window 对象是 ECMAScript 规定的 Global 对象,所以所有在全局作用域中声明的变量和函数都会变成 window 对象的属性和方法:

var age = 29;function sayAge(){    alert(this.age);} alert(window.age);//29 sayAge();//29 window. sayAge();//29

全局变量不能通过 delete 操作符删除,但直接定义在 window 对象上的属性却可以:

var age = 29;window.color = "black";delete window.age;//IE<9 时抛错,其他浏览器返回 falsedelete window.color;//IE<9 时抛错,其他浏览器返回 trueconsole.log(window.age);//29console.log(window.color);//undefined

试着访问未声明的变量会抛错,但通过查询 window 对象,可以判断出某个未经声明的变量是否存在:

var newValue = oldValue;//抛错,因为 oldValue 未定义var newValue = window.oldValue;//不会抛错,因为是通过 window,进行一次属性查询

注意: Windows Mobile 平台的 IE 浏览器不能通过 window.property = value 的模式,直接在 window 对象上创建新的属性和方法。但在全局作用域中声明的所有变量和函数,还是会变成 window 对象的成员。


2 窗口关系和框架

如果页面中包含框架(frame),那么每个框架都有拥有自己的 window 对象,并且保存在 frames 对象集合中。在 frames 中,可以通过索引(从 0 开始)或者框架名称来访问相应的 window 对象。每个 window 对象的 name 属性既是框架名称。

<frameset row="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>

top 对象始终指向最外层的框架,也就是浏览器窗口。

parent 对象指向当前框架的直接上层框架。如果页面没有嵌套框架,那么 parent 等于 top。

<frameset row="160,*">    <frame src="frame.htm" name="topFrame">    <frameset cols="50%,50%">        <frame src="anotherframe.htm" name="leftFrame">        <frame src="anotherframeset.html" name="rightFrame">    </frameset></frameset>

这个框架集包含了另一个框架集:

<frameset cols="50%,50%">    <frame src="red.htm" name="redFrame">    <frame src="blue.htm" name="blueFrame"></frameset>

self 对象就是 window 对象。

上述介绍的所有对象都是 window 对象的属性,因此可以将不同层次的 window 对象连缀起来写,例如:window.parent.parent.frames[0]。


注意: 使用框架后,浏览器中会存在多个 Global 对象。每个框架都有一套自己的构造函数,它们一一对应,但并不相等。比如,top.Object 并不等于 top.frames[0].Object。这会影响跨框架传递的对象使用 instanceof 操作符。


3 窗口位置

属性 IE、Safari、Opera、Chrome Firefox、Safari、Chrome 窗口相对于屏幕左边位置 screenLeft screenX 窗口相对于屏幕上边位置 screenRight screenY

跨浏览器取得窗口左边和上边的位置:

var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;console.log(leftPos);console.log(topPos);

注意:IE、Opera、Chrome 中的 screenLeft 和 screenTop 保存的是从屏幕左边和上边到由 window 对象表示的页面可见区域的距离。假设这里的 window 对象是最外层的对象,而且浏览器窗口紧贴屏幕的最上端,那么 screenTop 是位于页面可见区域上方的浏览器工具栏的像素高度。但在 Firefox 和 Safari 中,screenY 或 screenTop 中保存的是整个浏览器相对于屏幕的坐标值。总之,无法在跨浏览器的情况下取得窗口左边和上边的精确坐标值。

可以使用 moveTo() 和 moveBy() 将窗口精确地移动到一个新位置:

  • moveTo() 的两个参数:新位置的 x 坐标值,新位置的 y 坐标值。
  • moveBy() 的两个参数:水平方向上移动的像素数,垂直方向上移动的像素数。
window.moveTo(0,0);//将窗口移动到屏幕左上角window.moveBy(0,100);//将窗口向下移动 100 个像素window.moveTo(200,300);//将窗口移动到 (200,300)window.moveBy(-50,0);//将窗口向左移动 50 个像素

注意:

  • 这两个方法可以会被浏览器禁用。
  • 在 Opera 和 IE 7 以及更高版本,默认就是禁用的。
  • 这两个方法只对最外层的 window 对象有效。

4 窗口大小

因为各个浏览器标准不统一,所以无法跨浏览器取得窗口本身的大小。但在 IE、Firefox、Safari、Opera 和 Chrome 中,都定义了 document.documentElement.clientWidth 和 document.documentElement.clientHeight,这两个属性保存了页面的视口信息。但在 IE6 中,这两个属性必须在标准模式下才有效。如果是混杂模式,必须通过 document.body.clientWidth 和 document.body.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;    }}console.log("pageWidth:" + pageWidth);console.log("pageHeight:" + pageHeight);

Opera 和 Chrome 中,innerWidth 和 innerHeight 表示的是视口的大小。

可以使用 resizeTo() 和 resizeBy() 调整浏览器窗口的大小:

  • resizeTo() 参数:浏览器窗口新宽度,浏览器窗口新高度
  • resizeBy() 参数:新窗口与原窗口的宽度差,新窗口与原窗口的高度差
window.resizeTo(100,100);//调整为 100*100window.resizeBy(100,50);//调整为 200*150window.resizeTo(300,300);//调整为 300*300

注意:(同 moveTo() 和 moveBy() 一样,有这些限制)

  • 这两个方法可以会被浏览器禁用。
  • 在 Opera 和 IE 7 以及更高版本,默认就是禁用的。
  • 这两个方法只对最外层的 window 对象有效。

5 导航和打开窗口

window.open() 方法可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。它有 4 个参数:

  • 要加载的 URL。
  • 窗口目标,即已有窗口或框架的名称,会在它们之中进行加载;或者是这些特殊值(_self/_parent/_top/_blank)。
  • 特性字符串,如果没有传递,就会打开一个带有全部默认设置的新浏览器窗口。如果没有打开新窗口,会忽略这个值。
  • 新页面是否取代浏览器历史记录中当前加载页面(布尔值),只在不打开新窗口的情况下使用。

5.1 弹出窗口

特性字符串是一个逗号分隔的字符串,表示某些特性:

设置 值 说明 fullscreen yes/no 浏览器窗口是否最大化(仅 IE) height 数值 新窗口高度。不能小于 100 left 数值 新窗口的左坐标。不能是负值 location yes/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://xxx","height=400,width=400,top=10,left=10,resizable=yes");

window.open() 方法会返回一个指向新窗口的引用,可以调整这个新窗口的大小或者移动它的位置:

var win=window.open("http://xxx","height=400,width=400,top=10,left=10,resizable=yes");//opener 保存着打开它的原始窗口对象,只在弹出窗口的最外层(top)的 window 对象有定义console.log(win.opener == window);//true//调整大小win.resizeTo(500,500);//移动位置win.moveTo(100,100);//关闭自己win.close();//窗口的引用仍然存在,所以可以用来检测是否已关闭console.log(win.closed);//true

虽然弹出窗口中有一个指针指向打开它的原始窗口,但原始窗口中没有指针指向弹出窗口,所以在必要的时候需要手动来实现跟踪。

有些浏览器(IE8 或 Chrome )会使用独立进程来运行每一个标签页。将新创建的标签页的 opener 属性设置为 null,就会在独立的进程中运行新的标签页。但这样做后,这些标签页之间就没有办法通信了。

5.2 安全限制

因为曾经有一段时间,广告商肆无忌惮地使用弹出窗口功能来达到他们的宣传目的。所以有些浏览器开始在这方面添加了限制。

IE6 限制:

  • 不允许在屏幕外创建弹出窗口。
  • 不允许将弹出窗口移动到屏幕外。
  • 不允许关闭状态栏。

IE7 限制(在 IE6限制的基础上):

  • 不允许关闭地址栏。
  • 默认情况下不允许移动弹出窗口或调整大小。

Firefox 3 限制: 强制始终在弹出窗口显示地址栏。

Opera 限制:

  • 只会在主浏览器窗口中打开弹出窗口。
  • 不允许弹出窗出现在可以与系统对话框混淆的地方。

Chrome 限制: 只显示弹出窗的标题栏,并把它们放在浏览器窗口的右下角。


注意: 如果是直接打开本机硬盘中的网页,IE 会解除对弹出窗口的某些限制。但如果是运行本地的应用服务器,仍然会受到限制。


5.3 弹出窗口屏蔽程序

大多数浏览器都内置了弹出窗口屏蔽程序,这些可以把绝大多数的弹出窗口屏蔽掉。以下代码可以确定弹出窗口是否被屏蔽了:

var win = window.open("http://xxx","_blank");if (win == null){    console.log("The popup was blocked!");}

如果是浏览器扩展或者其他程序阻止了弹出窗口,那么 window.open() 会抛出一个错误,因此检测弹出窗口是否被屏蔽的通用程序是:

var blocked = false;try {    var newW = window.open("http://www.163.com", "_blank");    if (newW == null) {        blocked = true;    }} catch (ex) {    blocked = true;}if (blocked) {    console.log("The popup was blocked!");}

6 间歇调用和超时调用

JavaScript 是单线程语言,但可以让代码在特定的时刻运行。

setTimeout() 是超时调用的方法。它接受两个参数:

  • 要执行的代码。
  • 以毫秒表示的时间,即多少毫秒以后再执行代码。
//不建议传递字符串,会导致性能损失!!!setTimeout("console.log('Hello world!')", 1000);//推荐方式setTimeout(function () {    console.log("Hello world!");}, 1000);

为了控制要执行的代码,JavaScript 会把这些任务添加到一个任务队列中,然后再按队列的顺序执行。所以如果到了执行时间,这时的队列如果为空,则立即执行;如果队列不为空,则要等前面的任务执行完毕后,才能执行。

setTimeout() 会返回一个数值 ID,这是计划执行代码的唯一标识符,可以通过它取消尚未执行的超时调用:

//设置超时调用var timeoutId = setTimeout(function () {    console.log("Hello world!");}, 1000);//取消clearTimeout(timeoutId);

注意: 超时调用的代码是在全局作用域中执行的,所以函数中的 this 的值在非严格模式下指向 window 对象,在严格模式下是 undefined。


setInterval() 是间歇调用,即会按照指定的时间间隔重复执行设置的代码,直到间歇调用被取消或者页面被卸载。它也接受两个参数:

  • 要执行的代码。
  • 每次执行前需要等待的毫秒数。
//不建议传递字符串,会导致性能损失!!!setInterval("console.log('Hello World!')", 10000);//推荐setInterval(function () {    console.log("Hello World!");}, 10000);

setInterval() 也会返回一个 ID,它也可以在将来某个时刻取消间歇调用,这很重要,因为间歇调用会一直执行到页面被卸载为止:

var num = 0;var max = 10;var intervalId = null;function incrementNumber() {    num++;    //如果执行次数达到 max,就取消后续调用    if (num == max) {        clearInterval(intervalId);        console.log("Done");    }}intervalId = setInterval(incrementNumber, 500);

这也是使用超时调用来实现:

var num = 0;var max = 10;var intervalId = null;function incrementNumber() {    num++;    //如果执行次数达到 max,就设置另一个超时调用    if (num < max) {        setTimeout(incrementNumber,500);    }else{        console.log("Done");    }}setTimeout(incrementNumber, 500);

最好所有的间歇调用都用超时调用来模拟实现,因为在间歇调用中,后一个调用可能会在前一个调用结束之前启动运行,这不是我们希望看到的。

7 系统对话框

系统对话框的外观是由操作系统或浏览器的设置决定的,而且这些打开的对话框都是同步和模态的,也就是说打开它们的时候代码会停止执行,关掉后代码才会恢复执行。

通常使用 alert() 来生成“警告”对话框,来向用户显示一些他们无法控制的消息,比如错误消息。

confirm() 是确认对话框,它与 alert() 相比,多了一个“取消”按钮,可以检测 confirm() 返回的布尔值来判断用户的实际操作:

  • true 表示 OK。
  • false 表示点击了 Cancel 或者单击了右上角的 X 按钮。
    confirm() 通常用于确认用户是否真的想执行删除操作。
if(confirm("Are you sure?")){    console.log("I'm so glad you're sure!");}else{    console.log("I'm sorry to hear you're not sure.");}

prompt() 是提示框,与 confirm() 相比,又多了一个提示文本参数,它会返回用户输入的文本数据;如果用户点击了 Cancel 或者单击了右上角的 X 按钮,则它会返回 null。

var result = prompt("What is your name? ","");if (result !== null){    console.log("Welcome, " + result);}

Chrome 引入了新特性,如果当前脚本在执行过程中打开了两个或以上的多个窗口,那么从第二个对话框开始,每个对话框都会显示一个复选框,以便用户可以阻止后续的对话框显示。IE9 和 Firefox4 也实现这个特性。

查找和打印对话框也可以通过 JavaScript 打开,它们都是异步显示的,即可以将控制权立即交还给脚本:

window.print();//打印对话框window.find();//查找对话框

因为它们是异步的,所以不会受到 Chrome 新特性的影响,但可惜的是,它们无法收到用户在对话框进行的操作信息,所以用处有限。

0 0
原创粉丝点击