重温《JavaScript高级程序设计》—9.BOM
Jan 7, 2018前端js本篇内容
- window对象
- 间歇调用和超时调用、系统对话框
- location对象
- navigator对象
- screen对象
- history对象
在Web中使用JavaScript,BOM(浏览器对象模型)是核心。
window对象
BOM的核心对象是window,它表示浏览器的一个实例。
在浏览器中,window对象既是通过JavaScript访问浏览器窗口的一个接口,又是ECMAScript规定的Global对象。这意味着在网页中定义的任何一个对象、变量和函数,都以window作为其Global对象,也因此有权访问parseInt()等方法。
全局作用域
由于window对象同时扮演着ECMAScript中Global对象的角色,因此所有在全局作用域声明的变量、函数都会变成window对象的属性和方法。如1
2
3
4
5
6
7var age = 18;
function sayAge() {
console.log(this.age);
}
console.log(window.age); // 18
window.sayAge(); // 18
定义全局变量和在window对象上直接定义属性的差别:
- 全局变量不能通过delete操作符删除,在window对象上定义属性可以(定义的全局变量添加的window属性的[[Configurable]]特性的值为false,因此不能通过delete删除)。如
1
2
3
4
5
6
7
8var age = 18;
window.name = 'Micheal';
delete window.age; // IE < 9时报错,其他返回false
delete window.name; // IE < 9时报错,其他返回true
console.log(window.age); // 18
console.log(window.name); // undefined
IE8及更早的版本在遇到使用delete删除window属性的语句时,不管该属性最初是如何创建的,都会抛出错误。
- 尝试访问未声明的变量会抛出错误,但是通过查询window对象,可以知道某个可能未声明的变量是否存在。如
1
2
3
4var newValue = oldValue; // error
// 这样不会报错
var newValue = window.oldValue;
窗口关系及框架
如果页面中包含框架,则每个框架都拥有自己的window对象,并且保存在frames集合中。
在frames集合中,可以通过数值索引(从0开始,从左至右,从上到下)或者框架名称来访问相应的window对象。每个window对象都有一个name属性,其中包含框架的名称。如下页面:1
2
3
4
5
6
7
8
9
10
11
12<html>
<head>
<title></title>
</head>
<frameset rows="160,*">
<frame src="frame1.html" name="topframe"></frame>
<frameset cols="50%, 50%">
<frame src="frame2.html" name="leftframe"></frame>
<frame src="frame3.html" name="rightframe"></frame>
</frameset>
</frameset>
</html>
这个页面中,我们可以通过window.frames[0]或者window.frames[‘topframe’]来引用上方的框架。不过最好使用top来代替window,如top.frames[‘topframe’],因为top对象始终指向最高层的框架
与top相对的另一个window对象是parent,parent对象始终指向当前框架的直接上层框架。
除非最高层窗口是通过window.open()打开的,否则其window对象的name属性不会包含任何值。
与框架有关的最后一个对象是self,它始终指向window。实际上self和window对象可以互换使用。
窗口位置
取得窗口左边和上边的位置(不同浏览器有误差,无法再跨浏览器的条件下取得窗口左边和上边的精确坐标值)。1
2var leftPos = (typeof window.screenLeft === 'number') ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop === 'number') ? window.screenTop : window.screenY;
使用moveTo()和moveBy()方法倒是有可能将窗口精确地移动到一个新位置(但有可能被浏览器禁用)。这两个方法都接收两个参数,其中欧冠moveTo()接收的是新位置的x和y坐标值,moveBy()接收的是在水平和垂直方向上移动的像素数。如1
2window.moveTo(100, 200);
window.moveBy(-50, 10);
窗口大小
在IE9+、Firefox、Safari、opera、chrome中,outerWidth和outerHeight返回浏览器窗口本身的尺寸,innerWidth和innerHeight返回该容器中页面视图区的大小。
无法确定浏览器窗口本身的大小,但可以取得页面视口的大小。1
2
3
4
5
6
7
8
9
10
11
12var 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()接收新窗口与原窗口的宽度和高度之差。如1
2
3window.resizeTo(100, 200);
window.resizeBy(10, -50);
导航和打开窗口
使用window.open()方法即可以导航到一个特定的URL,也可以打开一个新的浏览器窗口。这个方法接收4个参数:要加载的URL、窗口目标、一个特性字符串以及一个表示新页面是否取代浏览器历史记录中当前加载页面的布尔值。最后一个参数只在不打开新窗口的情况下使用。如1
2// 相当于<a href="http://www.apple.com" target="appleFrame">
window.open('http://www.apple.com/', 'appleFrame');
第二个参数可以是特殊的窗口名称:_self、_parent、_top或_blank。
如果给window.open()传递的第二个参数并不是一个已经存在的窗口或框架,那么该方法就会根据在第三个参数位置上传入的字符串创建一个新窗口或新标签页。如果没有传入第三个参数,那么就会打开一个带有全部默认设置(工具栏、地址栏和状态栏等)的新浏览器窗口。
第三个参数是一个逗号分隔的设置字符串,表示在新窗口中都显示哪些特性。
设置 | 值 | 描述 |
---|---|---|
fullscreen | yes或no | 表示浏览器窗口是否最大化,仅IE |
height | 数值 | 表示新窗口的高度,不能小于100 |
left | 数值 | 表示新窗口的左坐标。不能是负值 |
location | yes或no | 表示是否在浏览器窗口中显示地址栏。(不同浏览器情况不同) |
menubar | yes或no | 表示是否在浏览器窗口中显示菜单栏。默认为no |
resizeable | yes或no | 表示是否可以通过拖动浏览器窗口的边框改变其大小。默认为no |
scrollbars | yes或no | 表示如果内容在视口显示不下,是否允许滚动。默认为no |
statue | yes或no | 表示是否在浏览器窗口中显示状态栏。默认为no |
toolbar | yes或no | 表示是否在浏览器窗口中显示工具栏。默认为no |
top | 数值 | 表示新窗口的上坐标。不能为负值 |
width | 数值 | 表示新窗口的宽度。不能小于100 |
如1
window.open('http://www.apple.com', 'appleFrame', 'height=400, top=10, left=20')
window.open()方法会返回一个指向新窗口的引用。通过这个返回的对象,可以像操作其他窗口一样操作新打开的窗口。如1
2
3
4
5
6
7var newWin = window.open('http://www.apple.com', 'appleFrame', 'height=400, top=10, left=20');
newWin.resizeTo(800, 600); // 调整大小
newWin.close(); // 关闭
console.log(newWin.closed); // true
新建的窗口的window对象有一个opener属性,其中保存着打开它的原始窗口对象。如1
2
3var newWin = window.open('http://www.apple.com', 'appleFrame', 'height=400, top=10, left=20');
console.log(newWin.opener == window); // true
将opener属性设置为null时,浏览器新创建的标签页不会与打开它的标签页通信。
如果是浏览器内置的屏蔽程序阻止的弹出窗口,那么window.open()很可能返回null。如果是浏览器扩展或其他程序阻止的弹出窗口,那么window.open()通常会抛出一个错误。
间歇调用和超时调用
mdn-setTimeout、mdn-setInterval
超时调用setTimeout(),间歇调用setInterval()。接收两个参数,第一个参数可以是一个包含JavaScript代码的字符串(类似于eval中的字符串),也可以是一个函数(传递字符串可能导致性能损失,因此不建议以字符串作为第一个参数);第二个参数是一个表示等待多长时间的毫秒数,但经过该时间后指定的代码不一定会执行(可了解js的执行模式)。
调用setTimeout()/setInterval()之后,该方法会返回一个数值ID,表示超时调用。这个超时调用ID是计划执行代码的唯一标识符,可以通过它来取消超时调用(setTimeout() -> clearTimeout(),setInterval() -> clearInterval())。
系统对话框
alert()、confirm()、prompt()方法,在此不过多描述。如1
2
3
4
5
6
7
8alert('hi!');
var bool = confirm('Are you ok ?');
if (bool) {
var name = prompt('What is your name?');
} else {
var reason = prompt('Why are you not ok?', 'I am busy');
}
这几个方法打开的对话框都是同步和模态的。
location对象
mdn-Location
w3cschool-Location
location对象提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。
location对象既是window对象的属性,也是document对象的属性。换句话说,window.location和document.location引用的是同一个对象。
属性名 | 例子 | 描述 |
---|---|---|
hash | ‘#test’ | 返回URL中的hash值,没有则返回空字符串 |
host | ‘www.apple.com:80' | 返回服务器名称和端口号(如果有) |
hostname | ‘www.apple.com' | 返回不带端口号的服务器名称 |
href | ‘http://www.apple.com' | 返回当前加载页面的完整URL(同location.toString()) |
pathname | ‘/public/‘ | 返回URL中的目录和文件名 |
port | ‘8080’ | 返回URL中指定的端口号 |
protocol | ‘http:’ | 返回页面使用的协议,http:或https: |
search | ‘?name=micheal’ | 返回URL的查询字符串 |
location.assign(),打开新URL并在浏览器的历史记录中生成一条记录。如果是将location.href或window.location设置为一个URL值,也会调用该assign()方法,如1
2window.location = 'http://www.apple.com';
location.href = 'http://www.apple.com';
另外修改location对象的其他属性(hash、search等)也可以改变当前加载的页面。
要禁止生成一条历史记录(不能后退到上一页面),使用replace()方法,只接收一个参数即导航到的URL。如1
location.replace('http://www.apple.com');
动态改变hash值不会刷新页面(因此可作路由功能),动态改变search会刷新页面。
reload()方法的作用是重新加载当前显示的页面。不加参数时会从浏览器缓存中重新加载。要清除缓存则应该加参数true,如1
location.reload(true)
navigator对象
属性或方法 | 描述 | IE | Firefox | Safari/Chrome | Opera |
---|---|---|---|---|---|
appCodeName | 浏览器的名称。通常是Mozilla | 3.0+ | 1.0+ | 1.0+ | 7.0+ |
appMinorVersion | 次版本信息 | 4.0+ | - | - | 9.5+ |
appName | 完整的浏览器名称 | 3.0+ | 1.0+ | 1.0+ | 7.0+ |
appVersion | 浏览器的版本,一般不与实际的浏览器版本对应 | 3.0+ | 1.0+ | 1.0+ | 7.0+ |
buildID | 浏览器编译版本 | - | 2.0+ | - | - |
cookieEnabled | 表示cookie是否启用 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
cpuClass | 客户端计算机中使用的CPU类型(x86、68K、Alpha、PPC或其他) | 4.0+ | - | - | - |
javaEnabled() | 表示当前浏览器是否启动了java | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
language | 浏览器的主语言 | - | 1.0+ | 1.0+ | 7.0+ |
mimeTypes | 在浏览器中注册的MIME类型数组 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
onLine | 表示浏览器是否连接到了因特网 | 4.0+ | 1.0+ | - | 9.5+ |
opsProfile | 作废 | 4.0+ | - | - | - |
oscpu | 客户端计算机的操作系统或使用的CPU | - | 1.0+ | - | - |
platform | 浏览器所在的系统平台 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
plugins | 浏览器中安装的插件信息的数组 | 4.0+ | 1.0+ | 1.0+ | 7.0+ |
perference() | 设置用户的首选项 | - | 1.5+ | - | - |
product | 产品名称(如Gecko) | - | 1.5+ | - | - |
productSub | 关于产品的次要信息(如版本) | - | 1.0+ | 1.0+ | - |
registerContentHandler() | 针对特定的MIME类型将一个站点注册为处理程序 | - | 2.0+ | - | - |
registerProtocolHandler() | 针对特定的协议将一个站点注册为处理程序 | - | 2.0 | - | - |
securityPolicy | 作废,安全策略的名称 | - | 1.0+ | - | - |
systemLanguage | 操作系统的语言 | 4.0+ | - | - | - |
taintEnabled() | 作废,表示是否允许变量被修改 | 4.0+ | 1.0+ | - | 7.0+ |
userAgent | 浏览器的用户代理字符串 | 3.0+ | 1.0+ | 1.0+ | 7.0+ |
userLanguage | 操作系统的默认语言 | 4.0+ | - | - | 7.0+ |
userProfile | 借以访问用户个人信息的对象 | 4.0+ | - | - | - |
vendor | 浏览器的品牌 | - | 1.0+ | 1.0+ | - |
vendorSub | 有关供应商的次要信息 | - | 1.0+ | 1.0+ | - |
userAgent属性常用于检测平台信息,如1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65/*
* PC
* 获取浏览器类型和版本
* @return {String}
*/
function getExplore() {
var sys = {},
ua = navigator.userAgent.toLowerCase(),
s;
(s = ua.match(/rv:([\d.]+)\) like gecko/)) ? sys.ie = s[1]:
(s = ua.match(/msie ([\d\.]+)/)) ? sys.ie = s[1] :
(s = ua.match(/edge\/([\d\.]+)/)) ? sys.edge = s[1] :
(s = ua.match(/firefox\/([\d\.]+)/)) ? sys.firefox = s[1] :
(s = ua.match(/(?:opera|opr).([\d\.]+)/)) ? sys.opera = s[1] :
(s = ua.match(/chrome\/([\d\.]+)/)) ? sys.chrome = s[1] :
(s = ua.match(/version\/([\d\.]+).*safari/)) ? sys.safari = s[1] :
0;
// 根据关系进行判断
if (sys.ie) return ('IE: ' + sys.ie)
if (sys.edge) return ('EDGE: ' + sys.edge)
if (sys.firefox) return ('Firefox: ' + sys.firefox)
if (sys.chrome) return ('Chrome: ' + sys.chrome)
if (sys.opera) return ('Opera: ' + sys.opera)
if (sys.safari) return ('Safari: ' + sys.safari)
return 'Unkonwn'
}
/*
* mobile
* 获取浏览器类型和版本
* return {String}
*/
function getMobileExplore() {
var ua = navigator.userAgent.toLowerCase();
if (~ua.indexOf('qq')) return 'qq'; // QQ或qq浏览器
if (~ua.indexOf('micromessenger')) return 'wchat'; // 微信
if (~ua.indexOf('weibo')) return 'weibo'; // 微博
if (~ua.indexOf('liebao')) return 'liebao'; // 猎豹浏览器
if (~ua.indexOf('uc')) return 'uc'; // uc浏览器
if (~ua.indexOf('baidu')) return 'baidu'; // 百度app或百度浏览器
if (~ua.indexOf('fxios')) return 'firefox'; // 火狐浏览器
if (~ua.indexOf('sogou')) return 'sogou'; // 搜狗浏览器
if (~ua.indexOf('mxios')) return 'maxthon'; // 遨游浏览器
return 'native'
}
/*
* 获取操作系统类型
* @return {String}
*/
function getOS() {
var userAgent = 'navigator' in window && 'userAgent' in navigator && navigator.userAgent.toLowerCase() || '';
var vendor = 'navigator' in window && 'vendor' in navigator && navigator.vendor.toLowerCase() || '';
var appVersion = 'navigator' in window && 'appVersion' in navigator && navigator.appVersion.toLowerCase() || '';
if (/mac/i.test(appVersion)) return 'MacOSX'
if (/win/i.test(appVersion)) return 'windows'
if (/linux/i.test(appVersion)) return 'linux'
if (/iphone/i.test(userAgent) || /ipad/i.test(userAgent) || /ipod/i.test(userAgent)) 'ios'
if (/android/i.test(userAgent)) return 'android'
if (/win/i.test(appVersion) && /phone/i.test(userAgent)) return 'windowsPhone'
}
检测浏览器中是否安装了特定的插件,对于非IE浏览器,可以使用plugins数组来达到这个目的。
plugin数组的每一项都包含下列属性
- name:插件的名字
- description: 插件的描述
- filename: 插件的文件名
- length: 插件所处理的MIME类型数量。
1 | // 非IE |
screen对象
属性 | 描述 | IE | Firefox | Safari/Chrome | Opera |
---|---|---|---|---|---|
availHeight | 屏幕的像素高度减系统部件高度之后的值(只读) | true | true | true | true |
availLeft | 未被系统部件占用的最左侧的像素值(只读) | - | true | true | - |
availLeft | 未被系统部件占用的最上方的像素值(只读) | - | true | true | - |
availWidth | 屏幕的像素宽度减系统部件宽度之后的值(只读) | true | true | true | true |
bufferDepth | 读、写用于呈现屏外位图的位数 | true | - | - | - |
colorDepth | 用于表现颜色的位数,多数是32(只读) | true | true | true | true |
deviceXDPI | 屏幕实际的水平DPI(只读) | true | - | - | - |
deviceYDPI | 屏幕实际的垂直DPI(只读) | true | - | - | - |
fontSmoothingEnabled | 表示是否启用了字体平滑(只读) | true | - | - | - |
height | 屏幕的像素高度 | true | true | true | true |
left | 当前屏幕距左边的像素距离 | - | true | - | - |
logicalXDPI | 屏幕逻辑的水平DPI(只读) | true | - | - | - |
logicalYDPI | 屏幕逻辑的垂直DPI(只读) | true | - | - | - |
pixelDepth | 屏幕的位深(只读) | - | true | true | true |
top | 当前屏幕距上边的像素距离 | - | true | - | - |
updateInterval | 读、写以毫秒表示的屏幕刷新时间间隔 | true | - | - | - |
width | 屏幕的像素宽度 | true | true | true | true |
screen对象基本上只用来表明客户端的能力
history对象
history对象保存着用户上网的历史记录,length属性表示历史记录的数量。
使用go()方法可以在用户的历史记录中任意跳转。只接收一个参数,数值或字符串(包含该字符串的第一个位置,可能后退或前进)。
go(-1)同back(),go(1)同forward()。
温习:
- 定义全局变量和在window对象上直接定义属性的两个差别;
- 框架中的全局变量frames、parent、self、top;
- 窗口方法及属性,如window.open()、opener;
- setTimeout()和setInterval()的使用与超时调用;
- location对象的属性和方法;
- navigator对象的属性;
- screen对象的属性
(完)
Author
My name is Micheal Wayne and this is my blog.
I am a front-end software engineer.
Contact: michealwayne@163.com