美文网首页
JS高程:读书摘要(五)BOM属性

JS高程:读书摘要(五)BOM属性

作者: Upcccz | 来源:发表于2018-12-28 20:03 被阅读0次

BOM

window 全局作用域

BOM的核心对象是window,它表示浏览器的一个实例。在浏览器中,window 对象有双重角色,它既是通过JavaScript 访问浏览器窗口的一个接口,又是ECMAScript 规定的Global 对象。因此所有在全局作用域中声明的变量、函数都会变成window 对象的属性和方法。

定义全局变量与在window 对象上直接定义属性还是有一点差别:全局变量不能通过delete 操作符删除,而直接在window 对象上的定义的属性可以。

// IE9不支持,会报错
var age = 29;
window.color = "red";
delete window.age; // return false
delete window.color; //return true
alert(window.age); //29
alert(window.color); //undefined

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

[[Configurable]]:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,即是否可配置。默认值为true。(window也是对象,在对象上定义属性,[[Configurable]]也是默认为true,可删除可配置)

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

//这里会抛出错误,因为oldValue 未定义
var newValue = oldValue;  // error
//这里不会抛出错误,因为这是一次属性查询
var newValue = window.oldValue; // undefined
窗口关系与框架

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

<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.frames[0])。我们知道,top 对象始终指向最高(最外)层的框架,也就是浏览器窗口。使用它可以确保在一个框架中正确地访问另一个框架。因为对于在一个框架中(例如上面的anotherframe.htmyetanotherframe.htm )编写的任何代码来说,其中的window 对象指向的都是那个框架的特定实例,而非最高层的框架。这两个框架中window.name是等于leftFramerightFrame

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

top 相对的另一个window 对象是parent。顾名思义,parent(父)对象始终指向当前框架的直接上层框架。在某些情况下,parent 有可能等于top;但在没有框架的情况下,parent 一定等于top(此时它们都等于window)。引入self 对象的目的只是为了与topparent 对象对应起来,因此它不格外包含其他值。所有这些对象都是window 对象的属性,可以通过window.parentwindow.top 等形式来访问。同时,这也意味着可以将不同层次的window 对象连缀起来,例如window.parent.parent.frames[0]top对象是无法被改变的,永远指向最顶层的窗口对象,而self对象、parent对象是可以被别的值替换的。

window对象.png

在使用框架的情况下,浏览器中会存在多个Global 对象。在每个框架中定义的全局变量会自动成为框架中window 对象的属性。由于每个window 对象都包含原生类型的构造函数,因此每个框架都有一套自己的构造函数,这些构造函数一一对应,但并不相等。例如,top.Object 并不等于top.frames[0].Object。这个问题会影响到对跨框架传递的对象使用instanceof 操作符。

窗口大小
  • window.innerHeight/innerWidth
    获取的是浏览器窗口的内部高度/宽度,包括了滚动条的宽度,IE 8 及更早 IE版本不支持这两个属性。
  • document.body.clientHeight/clientWidth
    不包滚动条等边线,会随窗口的显示大小改变。
  • document.documentElement.clientHeight/clientWidth
    表示HTML文档所在窗口的当前高度/宽度。在IE6 中,这些属性必须在标准模式下才有效;如果是混杂模式,就必须通过document.body.clientWidthdocument.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;
    }  
}
导航和打开窗口

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

  • 要加载的URL
  • 窗口目标,第二个参数也可以是下列任何一个特殊的窗口名称:_self_parent_top_blank
  • 一个特性字符串,第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。
  • 一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。只在不打开新窗口的情况下使用。

通常只须传递第一个参数,如果为window.open()传递了第二个参数,而且该参数是已有窗口或框架的名称,那么就会在具有该名称的窗口或框架中加载第一个参数指定的URL

//等同于< a href="http://www.wrox.com" target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
  • 关于_self_parent_top_blank
    • _self:在同一框架或窗口中打开所链接的文档。此参数为默认值,通常不用指定。
    • _blank :浏览器会另开一个新窗口显示链接
    • _parent : 将链接的文件载入含有该链接框架的父框架集或父窗口中。如果含有该链接的框架不是嵌套的,则在浏览器全屏窗口中载入链接的文件,就象_self参数一样。
    • _top : 在当前的整个浏览器窗口中打开所链接的文档,因而会删除所有框架。
  • 关于window.open()的第三个参数
    window.open()的第三个参数特性.png
    整个特性字符串中不允许出现空格,数值不用带单位px,不是用布尔值,而是用yes/no。
window.open("http://www.wrox.com/","wroxWindow",
            "height=400,width=400,top=10,left=10,resizable=yes");

这行代码会打开一个新的可以调整大小的窗口,窗口初始大小为400×400 像素,并且距屏幕上沿和左边各10 像素。
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();
// 可以使用closed属性检查窗口是否已关闭
alert(wroxWin.closed); //true

新创建的window 对象有一个opener 属性,其中保存着打开它的原始窗口对象。但原始窗口中并没有这样的指针指向弹出窗口。可以将opener属性设置为null(在Chrome中)来切断联系。

alert(wroxWin.opener == window); //true
wroxWin.opener = null;
弹出窗口屏蔽程序

在弹出窗口被屏蔽时,就应该考虑两种可能性。如果是浏览器内置的屏蔽程序阻止的弹出窗口,那么window.open()很可能会返回null。如果是浏览器扩展或其他程序阻止的弹出窗口,那么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()打开的弹出窗口是不是被屏蔽了。但要注意的是,检测弹出窗口是否被屏蔽只是一方面,它并不会阻止浏览器显示与被屏蔽的弹出窗口有关的消息。

setTimeout()超时调用和setInterval()间歇调用
  • setTimeout()
    • 第一个参数可以是一个包含JavaScript 代码的字符串(就和在eval()函数中使用的字符串一样),也可以是一个函数。由于传递字符串可能导致性能损失,因此不建议以字符串作为第一个参数。
    • 第二个参数是一个表示等待多长时间的毫秒数。
    • 定时器启动时候,第三个以后的参数是作为第一个function()的参数传进去。
function sum(x, y) {
    console.log(x+y) //4
}
setTimeout(sum, 1000, 1, 3);

但经过该时间后指定的代码不一定会执行。
JavaScript 是一个单线程序的解释器,因此一定时间内只能执行一段代码
为了控制要执行的代码,就有一个JavaScript 任务队列
这些任务会按照将它们添加到队列的顺序执行。
setTimeout()的第二个参数告诉JavaScript再过多长时间把当前任务添加到队列中。
如果队列是空的,那么添加的代码会立即执行;如果队列不是空的,那么它就要等前面的代码执行完了以后再执行。

调用setTimeout()之后,该方法会返回一个数值ID,表示超时调用。这个超时调用ID 是计划执行代码的唯一标识符,可以通过它来取消超时调用。要取消尚未执行的超时调用计划,可以调用clearTimeout()方法并将相应的超时调用ID 作为参数传递给它。

//设置超时调用
var timeoutId = setTimeout(function() {
    alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);

超时调用的代码都是在全局作用域中执行的,因此函数中this 的值在非严格模式下指向window 对象,在严格模式下是undefined

  • setInterval()
    它接受的参数与setTimeout()相同,调用setInterval()方法同样也会返回一个间歇调用ID,该ID 可用于在将来某个时刻取消间歇调用。要取消尚未执行的间歇调用,可以使用clearInterval()方法并传入相应的间歇调用ID。取消间歇调用的重要性要远远高于取消超时调用,因为在不加干涉的情况下,间歇调用将会一直执行到页面卸载。在使用超时调用时,没有必要跟踪超时调用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);

---- 用setTimeout来实现 ----

var num = 0;
var max = 10;
function incrementNumber() {
    num++;
    //如果执行次数未达到max 设定的值,则设置另一次超时调用
    if (num < max) {
        setTimeout(incrementNumber, 500);
    } else {
        alert("Done");
    }
}
setTimeout(incrementNumber, 500);
系统对话框
  • alert()方法的结果就是向用户显示一个系统对话框,其中包含指定的文本和一个OK(“确定”)按钮。
  • confirm()方法生成系统对话框,用于显示询问类的文本,除了显示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 打开的对话框,即“查找”和“打印”。这两个对话框都是异步显示的,能够将控制权立即交还给脚本。这两个对话框与用户通过浏览器菜单的“查找”和“打印”命令打开的对话框相同

//显示“打印”对话框
window.print();
//显示“查找”对话框
window.find(); 
// 可以传参用于寻找当前页面中展示的字符
// 查到返回true ,并高亮显示该词。否则返回false

相关文章

网友评论

      本文标题:JS高程:读书摘要(五)BOM属性

      本文链接:https://www.haomeiwen.com/subject/pwrslqtx.html