BOM是浏览器对象模型,它提供了很多用于访问浏览器的功能。
window对象
BOM的核心对象是window,它表示浏览器的一个实例。在浏览器中window既是JS访问浏览器窗口的一个接口,又是ES里规定的Global对象。也就是说在网页中定义的任何一个对象,变量和函数都以window作为其Global对象。
全局作用域
在全局作用域中声明的变量,函数都会变成window对象的属性和方法。
var age = 29;
window.color = "red";
function sayAge(){
alert(this.age);
}
alert(window.age); //29
sayAge(); //29
window.sayAge(); //29
不过定义全局变量和直接在window上定义属性还是不同的,全局变量不能通过delete操作符删除:
delete window.age; //returns false
delete window.color; //returns true
这是因为直接使用var添加的全局变量的[[Configurable]]为false。
在尝试访问未声明的变量会抛出错误,但是通过查询window对象可以知道某个可能未声明的变量是否存在:
var newValue = oldValue; //因为oldValue未定义,这样做会报错
var newValue = window.oldValue; //这里就不会有错误,这是一次属性查询,newValue的值是undefined
窗口关系及框架
如果页面中包含框架,则每个框架都有自己的window对象,且保存在frames集合中。可以通过数值索引或框架名称来访问响应的window对象。每个window对象都有一个name属性其中包含框架名称。不过最高层窗口例外,除非是通过window.open()打开的,否则最高层窗口的window对象的name属性不会包含任何值。
<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>
这里一共有三个框架,在最高层窗口中,你可以使用window.frames[0]或window.frames[“topFrame”]来访问这些框架。不过鉴于在这些框架中每个都有自己的window对象,最好使用top对象来代替windows。top很确定的指向最外层的框架的window对象,也就是浏览器窗口。即便是在某个内层框架使用时也不会出错。top.frames[0]或top.frames[“topFrame”]。
与上面top相对的window对象就是parent,parent始终指向当前框架的直接上层框架。
最后还有一个self对象,这个对象始终指向windows,它俩是等价的。
window.parent window.top,因为这两个返回的同样是其他框架的window对象,所以可以链式的继续访问下去。
要注意的是,在使用框架的情况下,浏览器中会出现多个Global对象,每个框架中定义的全局变量都会变成本框架中Global(window)的属性,每个window中都包含原生类型的构造函数,每个框架都有自己的构造函数。不过它们并不相等。top.Object和top.frames[0].Object并不相等。所以跨框架传递对象时使用instanceOf是有问题的。
窗口位置
window对象代表窗口相对于屏幕左边和上边的位置对于不同的浏览器有:screenLeft和screenTop或screenX和screenY。保险起见可以使用下面的办法来获取:
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
要注意的是,浏览器对这两个属性的返回规则也不大一样,有的就算在某个子框架里的window对象上调用也只会返回顶级window对象的位置,有的则会返回子框架的精确位置。
顶级的window对象还有两个方法:moveTo()和moveBy()用来将窗口移到或按偏移量移到某位置。
window.moveTo(200,300);
window.moveBy(0,100);
不同浏览器对这个的实现也不大一样。。。。有时还会被禁用掉。。。
窗口大小
有4个属性来表示窗口的大小innerWidth、innerHeight、outerWidth、outerHeight。不同的浏览器对这个的实现并不相同。对于outer的几个属性,有的浏览器表示浏览器窗口大小,有的表示页面视图区域大小。不过inner属性大家基本都表示页面视图区域的大小。
还有document.documentElement.clientWidth或document.documentElement.clientHeight。
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;
}
}
对于移动浏览器有两个概念,可见视口和布局视口。可见视口代表屏幕上可见页面区域的大小, 随着页面的缩放这些值会改变。通过window.innerWidth获取。布局视口是渲染后页面的实际大小。不会随着缩放改变。document.documentElement. client- Width存着这些。移动IE有差别。。。。。。
resizeTo和resizeBy可以调整窗口大小,一个是调整到,一个基于当前。
导航和打开窗口
window.open()方法这个方法接收4个参数,要加载的URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页的布尔值。最后一个参数只在不打开新窗口的情况下使用。
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);
wroxWin.close();
alert(wroxWin.opener == window); //true
窗口目标除了窗口名或框架名还可以是:_self _parent _top _blank
新创建的window对象会有一个指针指向打开它的原始窗口,但是窗口并不记录它打开的窗口们。
有时弹出窗口会被屏蔽,这样window.open()会弹出null或报错。
检测窗口是否被屏蔽的完全办法:
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!");
}
间歇调用和超时调用
超时调用
var timeoutId = setTimeout(function() {
alert("Hello world!");
}, 1000);
clearTimeout(timeoutId);
JS是单线程的,所以上面的代码只保证会在1秒后将要执行的代码添加到任务队列,如果这时任务队列是空的,那ok。
这个函数会返回一个数值ID,这个ID是即将执行的那段代码的唯一标识。可以通过他来取消尚未执行的超时调用。
间歇调用
var num = 0;
var max = 10;
var intervalId = null;
function incrementNumber() {
num++;
//到达最大值停止
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);
间歇调用有一个问题,就是后一个间歇调用有可能在前一个结束后没到规定时间就启动,而且如果没有正确的停下来,间歇调用将会一直执行下去。所以使用超时调用来模拟间歇调用是一个很好的办法。
var num = 0;
var max = 10;
function incrementNumber() {
num++;
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);
系统对话框
alert()、confirm()、prompt()。他们是同步的,会阻止代码运行
confirm()
这个有两个按钮,确认和取消,用户可以根据自己的需要选择,这个函数也会返回对应的true或false
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,会返回用户填写的字符串,否则返回null。
var result = prompt("What is your name? ", "");
if (result !== null) {
alert("Welcome, " + result);
}
window.print()和window.find()显示浏览器的查找和打印对话框。他们是异步的,和从浏览器菜单打开一样。
location对象
location对象代表了当前窗口所在位置,可以通过他来获取位置,也可以用他来设置位置。这个对象既是window的属性又是document的属性,是同一个引用。
获取
- hash:”#contents”。URL中hash#
- host:”www.wrox.com:80”。服务器名和端口号
- hostname:”www.wrox.com”。服务器名
- href:”http:/www.wrox.com”。完整URL
- pathname:”/WileyCDA/”。URL中的目录或文件名
- port:”8080”
- protocol:”http:”
- search:”?q=javascript”。查询字符串
设置
立即打开一个新的URL并在浏览器的历史记录中生成一条记录
//跳到http://www.baidu.com
location.assign("http://www.baidu.com");
window.location = "http://www.baidu.com";
location.href = "http://www.baidu.com";
// 初始URL http://www.wrox.com/WileyCDA/
location.hash = "#section1"; //"http://www.wrox.com/WileyCDA/#section1"
location.search = "?q=javascript"; //"http://www.wrox.com/WileyCDA/?q=javascript"
location.hostname = "www.yahoo.com"; //"http://www.yahoo.com/WileyCDA/"
location.pathname = "mydir"; //"http://www.yahoo.com/mydir/"
location.port = 8080; //"http://www.yahoo.com:8080/WileyCDA/"
打开新的URL但不生成历史记录,也就不能后退
location.replace("http://www.wrox.com/");
重新加载当前页面
location.reload(); //自动选择最有效的加载方式
location.reload(true); //强制从服务器加载
navigator对象
这里面主要包含着一些浏览器和操作系统的信息。
appCodeName
appMinorVersion
appName
appVersion
buildID
cookieEnabled
cpuClass
javaEnabled()
language
mimeTypes
onLine
opsProfile
oscpu
platform
plugins
preference()
product
productSub
registerContentHandler()
registerProtocolHandler()
securityPolicy
systemLanguage
taintEnabled()
userAgent
userLanguage
userProfile
vendor
vendorSub
检查插件
IE和非IE的差别太大,创建两套检测方法。
//非IE,直接访问plugins数组查名字就行,名字可以是一部分不一定准确
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;
}
//IE得知道确切的名字,代码尝试实例化一个这样的对象,成功了就代表有这个插件
function hasIEPlugin(name){
try {
new ActiveXObject(name);
return true;
} catch (ex){
return false;
}
}
function hasQuickTime(){
var result = hasPlugin("QuickTime");
if (!result){
result = hasIEPlugin("QuickTime.QuickTime");
}
return result;
}
alert(hasQuickTime());
注册处理程序
registerContentHandler()接收3个参数,要处理的MIME类型,可以处理该MIME类型页面的URL以及应用程序的名称。
navigator.registerContentHandler("application/rss+xml", "http://www.somereader.com?feed=%s", "Some Reader");
registerProtocolHandler()接收3个参数,要处理的协议,可以处理该协议的URL以及应用程序的名称。
navigator.registerProtocolHandler("mailto", "http://www.somemailclient.com?cmd=%s", "Some Mail Client");
screen对象
基本就是可以获取各种东西的大小
availHeight — — — — availLeft — — availTop — — availWidth — — — — bufferDepth — colorDepth — — — —deviceXDPI deviceYDPI fontSmoothingEnabled height — — — — left — logicalXDPI DPI — logicalYDPI DPI — pixelDepth
history对象
history是window对象的属性,每个页面都有自己的history对象与自己的window对象关联。出于安全考虑,不能获得用户浏览过得URL,通过go方法可以在不知道URL的情况下跳转。
history.go(-1);
history.go(2);
history.go("wrox.com"); //跳转到最近的包含这个字符串的页面
history.back();
history.forward();
history还有一个length属性,这个可以用来判断历史列表中有几个页面。对于刚打开的页面历史记录中的就是1。