JavaScript 高级程序设计(第8章 BOM)

第8章 BOM

1. window对象

1. BOM 的核心对象是 window,它表示浏览器的一个实例。
2. window 对象有双重角色, 它既是通过 JavaScript 访问浏览器窗口的一个接口,又是 ECMAScript 规定的 Global 对象。

(1) 全局作用域

window 对象同时扮演着 ECMAScript 中 Global 对象的角色,因此所有在全局作用域中声明的变量、函数都会变成 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

使用 var 语句添加的 window属性有一个名为[[Configurable]]的特性,这个特性的值被设置为 false,因此这样定义的属性不可以通过 delete 操作符删除。

尝试访问未声明的变量会抛出错误,但是通过查询 window 对象,可以知 道某个可能未声明的变量是否存在。

//这里会抛出错误,因为 oldValue 未定义 
var newValue = oldValue;
//这里不会抛出错误,因为这是一次属性查询 
//newValue 的值是 undefined
var newValue = window.oldValue;

(2) 窗口关系及框架

  1. 如果页面中包含框架,则每个框架都拥有自己的 window 对象,并且保存在 frames 集合中。
  2. 在 frames 集合中,可以通过数值索引(从 0 开始,从左至右,从上到下)或者框架名称来访问相应的 window对 象。
  3. 每个 window 对象都有一个 name 属性,其中包含框架的名称。
  4. top 对象始终指向最高(最外)层的框架,也就是浏览器窗口。使用它可以确保在一个 框架中正确地访问另一个框架。因为对于在一个框架中编写的任何代码来说,其中的 window 对象指向 的都是那个框架的特定实例,而非最高层的框架。`
  5. parent(父)对象始终指向当前框架的直接上层框架。在某些情况下,parent 有可能等于 top;但在没有框架的情况下,parent 一定等于 top(此时它们都等于 window)。
  6. 这些对象都是 window 对象的属性,可以通过window.parent、window.top 等形式来访问。 同时,这也意味着可以将不同层次的 window 对象连缀起来,例如window.parent.parent.frames[0]。
  1. 在使用框架的情况下,浏览器中会存在多个 Global 对象。在每个框架中定义的全局变量会自动成为框架中 window 对象的属性。由于每个 window 对象都包含原生 类型的构造函数,因此每个框架都有一套自己的构造函数,这些构造函数一一对应, 但并不相等。例如,top.Object 并不等于 top.frames[0].Object。这个问题会影响到对跨框架传递的对象使用 instanceof 操作符。

(3) 窗口位置

  1. IE、Safari、Opera 和 Chrome 都提供了 screenLeft 和 screenTop 属性,分别用于表示窗口相对于屏幕左边和上边的位置。
  2. 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;
  1. 在 IE、Opera 中,screenLeft 和 screenTop 中保存 的是从屏幕左边和上边到由 window 对象表示的页面可见区域的距离。换句话说,如果 window 对象是 最外层对象,而且浏览器窗口紧贴屏幕最上端——即 y 轴坐标为 0,那么 screenTop 的值就是位于页面可见区域上方的浏览器工具栏的像素高度。
  2. 但是,在 Chrome、Firefox 和 Safari 中,screenY 或screenTop 中保存的是整个浏览器窗口相对于屏幕的坐标值,即在窗口的 y 轴坐标为 0 时返回 0。
  1. Firefox、Safari 和 Chrome 始终返回页面中每个框架的 top.screenX 和 top.screenY 值。即使在页面由于被设置了外边距而发生偏移的情况下,相对于 window 对象使用 screenX 和 screenY 每次也都会返回相同的值。
  2. 而 IE 和 Opera 则会给出框架相对于屏幕边界的精确坐 标值。

窗口精确地移动到一个新位置:

moveTo() 方法:接收的是新位置的 x 和 y 坐标值。
moveBy()方法:接收的是在水平和垂直方向上移动的像素数。

//将窗口移动到屏幕左上角 
window.moveTo(0,0);
//将窗向下移动 100 像素 
window.moveBy(0,100);
//将窗口移动到(200,300) 
window.moveTo(200,300);
//将窗口向左移动 50 像素 
window.moveBy(-50,0);
  1. moveTo() 和 moveBy()方法在 Opera 和 IE 7(及更高版本)中默认就是禁用的。
  2. 这两个方法都不适用于框架,只能对最外层的 window 对象使用。

(4) 窗口大小

  1. 在 IE9+、Safari 和 Firefox 中,outerWidthouterHeight 返回浏览器窗口本身的尺寸(无论是从最外层的 window 对象还是从某个框架访问)。在 Opera 中,这两个属性的值表示页面视图容器的大小。
  2. innerWidth 和 innerHeight 则表示该容器中页面视图区的大小(减去边框宽度)。
  3. 在 Chrome 中,outerWidth、outerHeight 与 innerWidth、innerHeight 返回相同的值,即视口(viewport)大小而非浏览器窗口大小。
  1. 在 IE、Firefox、Safari、Opera 和 Chrome 中,document.documentElement.clientWidth 和 document.documentElement.clientHeight 中保存了页面视口的信息。
  2. 在 IE6 中,这些属性必须在 标准模式下才有效;如果是混杂模式,就必须通过 document.body.clientWidth 和 document.body. clientHeight 取得相同信息。
    6.而对于混杂模式下的 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;
        }
}

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()方法

  1. 既可以导航到一个特定的 URL,也可以打开一个新的浏览器窗口。
  2. 接收 4 个参数:要加载的 URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。
  3. window.open()传递了第二个参数,而且该参数是已有窗口或框架的名称,那么就会在具有该名称的窗口或框架中加载第一个参数指定的 URL。否则,就 会创建一个新窗口。第二个参数也可以是下列任何一个特殊的窗口名 称:_self、_parent、_top 或_blank。。

* 弹出窗口

  1. 如果给 window.open()传递的第二个参数并不是一个已经存在的窗口或框架,那么该方法就会根据在第三个参数位置上传入的字符串创建一个新窗口或新标签页。
  2. 如果没有传入第三个参数,那么就会 打开一个带有全部默认设置(工具栏、地址栏和状态栏等)的新浏览器窗口(或者打开一个新标签页— —根据浏览器设置)。
  3. 在不打开新窗口的情况下,会忽略第三个参数。
  4. 第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。
特性字符串

window.open("http://www.wrox.com/","wroxWindow",
            "height=400,width=400,top=10,left=10,resizable=yes");
  1. window.open()方法会返回一个指向新窗口的引用。引用的对象与其他 window 对象大致相似,但 我们可以对其进行更多控制。
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
//调整大小 
wroxWin.resizeTo(500,500);
//移动位置 
wroxWin.moveTo(100,100);
//调用 close()方法还可以关闭新打开的窗口。
wroxWin.close();
  1. 对于浏览器的主窗口,如果没有得到用户的允许是不能关闭它的。不过,弹出窗口倒是可以调用top.close()在不经用户允许的情况 下关闭自己。
  1. 新创建的 window 对象有一个 opener 属性,其中保存着打开它的原始窗口对象。
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
 "height=400,width=400,top=10,left=10,resizable=yes");
alert(wroxWin.opener == window);   //true

* 安全限制
* 弹出窗口屏蔽程序

  1. 如果是浏览器内置的屏蔽程序阻止的弹出窗口,那 么 window.open()很可能会返回 null。
  2. 如果是浏览器扩展或其他程序阻止的弹出窗口,那么 window.open()通常会抛出一个错误。
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) 间歇调用和超时调用
超时调用:在指定的时间过后执行代码。

  1. 超时调用需要使用 window 对象的 setTimeout()方法,它接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。
  2. clearTimeout()方法,取消尚未执行的超时调用计划。
//设置超时调用
var timeoutId = setTimeout(function() {
    alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);

间歇调用:每隔指定的时间就执行一次代码。

  1. 置间歇调用的方法是 setInterval(),接受两个参数:要执行的代码和以毫秒表示的时间(即在执行代码前需要等待多少毫秒)。
  2. clearInterval()方法,取消间歇调用。
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("Done");
    }
}
setTimeout(incrementNumber, 500);

在开发环境下,很少使用真正的间歇调用,原因是后一个间歇调用可能会在前一个间歇调用结束之前启动。

(7) 系统对话框

  1. 浏览器通过 alert()、confirm()和 prompt()方法可以调用系统对话框向用户显示消息。
  2. 系统对 话框与在浏览器中显示的网页没有关系,也不包含 HTML。它们的外观由操作系统及(或)浏览器设置 决定,而不是由 CSS 决定。
  3. 这几个方法打开的对话框都是同步和模态的。也就是说,显示这些对话框的时候代码会停止执行,而关掉这些对话框后代码又会恢复执行。

alert()方法: 接受一个字符串并将其显示给用户。
confirm()方法:返回的布尔值:true 表示单击了 OK,false 表示单击了 Cancel 或单击了右上角的 X 按钮。
prompt()方法:用于提示用户输入一些 文本。提示框中除了显示 OK 和 Cancel 按钮之外,还会显示一个文本输入域,以供用户在其中输入内容。 prompt()方法接受两个参数:要显示给用户的文本提示和文本输入域的默认值(可以是一个空字符串)。

还有两个可以通过 JavaScript 打开的对话框,即“查找”和“打印”。这两个对话框都是异步显示 的,能够将控制权立即交还给脚本。这两个对话框与用户通过浏览器菜单的“查找”和“打印”命令 打开的对话框相同。

//显示“打印”对话框
 window.print();
//显示“查找”对话框 
window.find();

2. location对象

  1. location 提供了与当前窗口中加载的文档有关的信息,还提供了一 些导航功能。
  2. location 对象是很特别的一个对象,因为它既是 window 对象的属性,也是 document 对象的属性;换句话说,window.locationdocument.location 引用的是同一个对象。
location对象属性

(1) 查询字符串参数

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"

(2) 位置操作
assign()方法:立即打开新 URL 并在浏览器的历史记录中生成一条记录。

将 location.href 或 window.location 设置为一个 URL 值,也会以该值调用 assign()方法。

 window.location = "http://www.wrox.com";
 location.href = "http://www.wrox.com";

replace()方法:接受一个参数,即要导航到的 URL;结果虽然会导致浏览器位置改变,但不会在历史记录中生成新记录

reload()方法:作用是重新加载当前显示的页面。

如果调用 reload() 时不传递任何参数,页面就会以最有效的方式重新加载。也就是说,如果页面自上次请求以来并没有改变过,页面就会从浏览器缓存中重新加载。如果要强制从服务器重新加载,则为该方法传递参数 true。

3. navigator对象

属性和方法

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

该数组中的每一项都包含下列属性:

  1. name:插件的名字。
  2. description:插件的描述。
  3. filename:插件的文件名。
  4. length:插件所处理的 MIME 类型数量。
//检测插件(在 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"));

在 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"));

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

(2) 注册处理程序
registerContentHandler()registerProtocolHandler()方 法这两个方法可以让一个站点指明 它可以处理特定类型的信息。

registerContentHandler()方法接收三个参数:要处理的 MIME 类型、可以处理该 MIME 类型的页面的 URL 以及应用程序的名称。

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");

4. screen 对象

screen 对象基本上只 用来表明客户端的能力,其中包括浏览器窗口外部的显示器的信息,如像素宽度和高度等。

screen属性.png

5. history对象

  1. go()方法可以在用户的历史记录中任意跳转,接受一个参数, 表示向后或向前跳转的页面数的一个整数值。
//后退一页
 history.go(-1);
//前进一页
 history.go(1);
//前进两页
 history.go(2);

go()方法传递一个字符串参数,此时浏览器会跳转到历史记录中包含该字符串的第一个 位置——可能后退,也可能前进,具体要看哪个位置最近。如果历史记录中不包含该字符串,那么这个 方法什么也不做。

//跳转到最近的 wrox.com 页面 
history.go("wrox.com");
//跳转到最近的 nczonline.net 页面
history.go("nczonline.net");

2.back()forward()方法

//后退一页
 history.back();
//前进一页
 history.forward();
  1. history 对象还有一个length 属性,保存着历史记录的数量。对于加载到窗口、标签页或框架中的第一个页面而言, history.length 等于 0


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容