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

2018-12-28  本文已影响0人  Upcccz

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 操作符。

窗口大小
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 个参数:

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

//等同于< a href="http://www.wrox.com" target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
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()间歇调用
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

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);
系统对话框
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("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
上一篇 下一篇

猜你喜欢

热点阅读