BOM
- ECMAScript是JavaScript的核心,但如果要在Web中使用JS,那么BOM(浏览器对象模型)则无疑才是真正的核心。BOM提供了很多对象,用于访问浏览器的功能,这些功能与任何页面内容无关。
window对象
- BOM的核心对象是window,它表示浏览器的一个实例。在浏览器中,window对象有双重角色,它既是通过JS访问浏览器的接口,又是ECMAScript规定的Global对象。因此在页面中定义的任何一个对象、变量和函数,都有权访问parseInt()等方法。
全局作用域
- 所有在全局作用域中声明的变量、函数都会成为window对象的属性和方法。
var age = 23;
function sayAge() {
alert(this.age);
}
alert(window.age);//age定义在全局作用域中,也就是window对象的属性
sayAge();//sayAge定义在全局作用域中,也就是window对象的方法,this指向window
window.sayAge();//同上
- 定义在全局作用域中的属性或方法和直接定义为window对象的属性或方法还是有一点小区别:全局变量不能通过delete操作符删除,而直接定义在window对象上的属性或方法可以。
var age = 29;
window.color = "red";
//throws an error in IE < 9, returns false in all other browsers
delete window.age;
//throws an error in IE < 9, returns true in all other browsers
delete window.color; //returns true
alert(window.age); //29
alert(window.color); //undefined
- 这是因为直接在全局作用域上定义的属性中的[[Configurable]]特性会被设成false,所以就不能用delete操作符删除了。另外,尝试访问未声明的变量会抛出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在。
//错误,oldValue未定义
var newValue = oldValue;
------------------------
//不会抛出错误,这里是一次属性查询,newValue == undefined
var newValue = window.oldValue;
窗口关系及框架
- 如果页面中包含框架,则每个框架都拥有自己的window对象,并且保存在frames集合中。在frames集合中,可以通过数值索引(从0开始,从左到右,从上到下)或者框架名称来访问相应的window对象。每个window对象都有一个name属性,其中包含框架的名称。
<frameset rows="100,*" name = "test">
<frame src="frame.htm" name="topFrame">
<frameset cols="50%,50%">
<frame src="anotherframe.htm" name="leftFrame">
<frame src="anotherframeset.htm" name="rightFrame">
</frameset>
</frameset>
- top对象始终指向最高(最外)层的框架,也就是浏览器窗口。
- parent对象始终指向当前框架的直接上层框架。在没有框架的情况下,parent等于top(window)
- 除非最高层窗口是通过window.open()打开的,否则window对象的name属性不会包含任何值。
- self对象始终指向window。
- 在使用框架的情况下,浏览器中会有多个Global对象。由于每个window对象都包含原生类型的构造函数,因此每个框架都有自己一套的构造函数,他们一一对应但并不相等。例如top.Object 并不等于top.frames[0].Object,同时也会影响到跨框架的instanceof操作符的结果。
窗口位置
- IE、Safari、Opera、Chrome都提供了screenLeft和screenTop属性,分别表示窗口相对于屏幕左边和上边的位置。Firefox则是使用screenX和screenY。Safari、Chrome同时支持这四个属性。Opera也支持这4个属性,但是并没有对应。通过以下代码可以获得浏览器的位置。
var leftPos = (typeof window.screenLeft == "number") ?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ?
window.screenTop : window.screenY;
alert("Left: " + leftPos);
alert("Top: " + topPos);
- 通过moveTo()和moveBy()可以移动浏览器窗口,不过这两个方法可能会被浏览器禁用。并且这两个方法只能对最外层的window对象使用。
//移动到屏幕左上角
window.moveTo(0, 0);
//向下100像素
window.moveBy(0, 100);
//移动到屏幕200 300
window.moveTo(200, 300);
//像左移动50像素
window.moveTo(-50, 0);
窗口大小
- IE9+、Firefox、Safari、Opera和Chrome都提供了四个属性:innerWidth、innerHeight、outerWidth和outerHeight。前面两个返回视口大小,后面两个返回浏览器大小。在Chrome中都是返回视口大小而非浏览器大小。下面的例子返回视口大小:
var pageWidth = window.innerWidth,
pageHeight = window.innerHeight;
if (typeof pageWidth != "number"){
//ie8- 下没有这个属性,如果是标准模式
if (document.compatMode == "CSS1Compat"){
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
//如果是混杂模式
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
alert("Width: " + pageWidth);
alert("Height: " + pageHeight);
- 通过resizeTo()和resizeBy()可以调整浏览器窗口大小,不过这两个方法可能会被浏览器禁用。并且这两个方法只能对最外层的window对象使用。
导航和打开窗口
- 使用window.open()方法既可以导航到一个特定的URL,也可以打开一个新的浏览器窗口。这个方法可以接收4个参数:要加载的URL,窗口目标,一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。通常只需传递第一个参数,最后一个参数只在不打开新窗口的情况下使用。
- 如果为window.open()传递了第二个参数,而且该参数是已有窗口或框架的名称,那么就会在指定的位置加载新的URL。
//等同于<a href="http://blog.csdn.net" target="topFrame"></a>
window.open("http://blog.csdn.net", "topFrame");
- 运行上面的代码,如果有一个名叫”topFrame”窗口或者框架,则会在该位置加载URL,否则就创建一个新窗口并命名为”topFrame”。此外第二个参数也可以是特殊的窗口名称:_self,_parent,_top或者_blank。
弹出窗口
- 如果给window.open()传递的第二个参数并不存在(存在则忽略第三个参数),那么该方法就会第三个参数创建一个新窗口或者新的标签页(不传就默认)。第三个参数是一个逗号分隔的字符串(不允许带空格),表示新窗口都有哪些特性。下面是选项:
设置 | 值 | 说明 |
---|---|---|
top | 数值 | 左坐标,不能为负数 |
left | 数值 | 上坐标,不能为负数 |
height | 数值 | 高度,不能小于100 |
width | 数值 | 宽度,不能小于100 |
fullscreen | yes/no | 表示窗口是否最大化。仅限IE |
location | yes/no | 表示是否在窗口中显示地址栏。设置为no,可能隐藏也可能禁用 |
menubar | yes/no | 是否显示菜单栏,默认为no |
toolbar | yes/no | 是否显示工具栏,默认为no |
resizable | yes/no | 是否可拖动边框改变大小,默认为no |
scrollbars | yes/no | 表示是否允许滚动,默认为no |
- window.open()还会返回新窗口对象的引用,可以通过这个再去操作新窗口。
- 调用窗口引用的close()方法可以关闭窗口,但是只能关闭open()出来的窗口。窗口关闭以后,引用还在,但是除了像下面用来检测closed属性之外已经没有其他用处了。还有opener属性,保存着打开它的原始窗口的引用。
var wroxWin = window.open("xxx", "wroxWin","width=400, height=400");
alert(wroxWin.opener == window);//true
wroxWin.close();
alert(wroxWin.closed);//true
将opener设为null就是告诉浏览器新创建的标签页不需要和打开它的标签页通信。在Chrome中可以使两个标签页在独立的进程中运行。(这一块我不是很感兴趣,省略了很多,有兴趣的同学去看原书,后面还有一段。)
间歇调用和超时调用
- JS是单线程语言,但是它允许通过设置超时值和间歇时间来调度代码在特定的时刻执行。
- 超时调用需要使用window对象的setTimeout()方法,它接收2个参数:要执行的代码和以毫秒表示的时间。其中第一个参数可以是一个字符串(就像在eval()中一样),也可以是一个函数。
//avoid!
setTimeout("alert('Hello world!') ", 1000);
//preferred
setTimeout(function() {
alert("Hello world!");
}, 1000);
- 虽然说第二个参数是表示等待多长时间的毫秒数,但是经过这么长时间代码不一定会马上执行。因为JS是单线程解释器,因此此处有一个队列的概念,第二个参数的时间过完,会将该任务加入队列。如果队列为空,则马上执行。
- setTimeout()会返回一个数值ID,通过这个ID,再通过clearTimeout()传入该ID即可取消该超时调用。
//set the timeout
var timeoutId = setTimeout(function() {
alert("Hello world!");
}, 1000);
clearTimeout(timeoutId);
- 非严格模式下超时调用函数中的this指向window,严格模式下指向undefined。
- setInterval()方法为间歇调用,第一次和超时调用没有区别,只不过会持续地进行超时调用。同理,使用clearInterval()能够取消间歇调用。
var num = 0;
var max = 10;
var intervalId = null;
function incrementNumber() {
num++;
//if the max has been reached, cancel all pending executions
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);
var num = 0;
var max = 10;
function incrementNumber() {
num++;
//if the max has not been reached, set another timeout
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);
系统对话框
- alert()、confirm()、prompt()方法可以调用系统对话框向用户显示消息。alert()就不多说了,主要说一下confirm()和prompt()的用法。
- 先来看看confirm()的经典用法:
if (confirm("are you sure?")) {
alert("yes, I sure!");
} else {
alert("no!");
}
- confirm()会弹出一个对话框,和alert()的区别是confirm()可以选择确定还是取消。相应的confirm()就会返回true或者false。
- prompt()会弹出一个输入框,用户在输入框内填入字符串,单击确定,则prompt()会返回一个字符串。如果什么都不填,单击确定返回空字符串。如果单击取消,则返回null。注意不是undefined,这里的null可以理解为此处本应有一个值,只是它是空的。
//第二个参数为弹窗的默认值
var result = prompt("what's you name?", "hange");
if (result) {//这里回味一下字符串转换,空字符串转换boolean为false
alert("hello, " + result);
}
alert(result);
- 此外还有两个不常用的对话框,他们的异步的,不会中断JS的执行。
//显示打印对话框
window.print();
//显示查找对话框 试了IE和Chrome都无效
window.find();