12.3 - 12.5 navigator对象、screen对象、history对象
12.3 navigator 对象
只要浏览器启用JavaScript,navigator 对象就一定存在。navigator对象的属性通常用于确定浏览器的类型。
12.3.1 检查插件
除IE10 及更低版本外的浏览器,都可以通过plugins 数组来确定。这个数组中的每一项都包含如下属性。
-
name:插件名称。
-
description:插件介绍。
-
filename:插件的文件名。
-
length:由当前插件处理的MIME 类型数量
检测插件就是遍历浏览器中可用的插件,并逐个比较插件的名称,如下所示:
// 插件检测,IE10 及更低版本无效
let hasPlugin = function(name) {
name = name.toLowerCase();
for (let plugin of window.navigator.plugins){
if (plugin.name.toLowerCase().indexOf(name) > -1){
return true;
}
}
return false;
}
// 检测Flash
alert(hasPlugin("Flash"));
// 检测QuickTime
alert(hasPlugin("QuickTime"));
旧版本IE中的插件检查
IE10 及更低版本中检测插件的问题比较多,因为这些浏览器不支持Netscape 式的插件。在这些IE中检测插件要使用专有的ActiveXObject,并尝试实例化特定的插件。IE 中的插件是实现为COM 对象的,由唯一的字符串标识。例子:
// 在旧版本IE 中检测插件
function hasIEPlugin(name) {
try {
new ActiveXObject(name);
return true;
} catch (ex) {
return false;
}
}
// 检测Flash
alert(hasIEPlugin("ShockwaveFlash.ShockwaveFlash"));
// 检测QuickTime
alert(hasIEPlugin("QuickTime.QuickTime"));
通用的插件检查
因为检测插件涉及两种方式,所以一般要针对特定插件写一个函数,而不是使用通常的检测函数。
// 在所有浏览器中检测Flash
function hasFlash() {
var result = hasPlugin("Flash");
if (!result){
result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
}
return result;
}
// 在所有浏览器中检测QuickTime
function hasQuickTime() {
var result = hasPlugin("QuickTime");
if (!result){
result = hasIEPlugin("QuickTime.QuickTime");
}
return result;
}
// 检测Flash
alert(hasFlash());
// 检测QuickTime
alert(hasQuickTime());
12.3.2 注册处理程序
现代浏览器支持navigator 上的(在HTML5 中定义的)registerProtocolHandler()方法。这个方法可以把一个网站注册为处理某种特定类型信息应用程序。
要使用registerProtocolHandler()方法,必须传入3 个参数:要处理的协议(如"mailto"或"ftp")、处理该协议的URL,以及应用名称。比如,要把一个Web 应用程序注册为默认邮件客户端,可以这样做:
navigator.registerProtocolHandler("mailto",
"http://www.somemailclient.com?cmd=%s",
"Some Mail Client");
12.4 screen对象
window 的另一个属性screen 对象,是为数不多的几个在编程中很少用的JavaScript 对象。这个对象中保存的纯粹是客户端能力信息,也就是浏览器窗口外面的客户端显示器的信息,比如像素宽度和像素高度。
12.5 history对象
history 对象表示当前窗口首次使用以来用户的导航历史记录。因为history 是window 的属性,所以每个window 都有自己的history 对象。
12.5.1 导航
go()方法可以在用户历史记录中沿任何方向导航,可以前进也可以后退。这个方法只接收一个参数,这个参数可以是一个整数,表示前进或后退多少步。
// 后退一页
history.go(-1);
// 前进一页
history.go(1);
// 前进两页
history.go(2);
go()有两个简写方法:back()和forward()。
// 后退一页
history.back();
// 前进一页
history.forward();
对于窗口或标签页中加载的第一个页面,history.length等于1。
if (history.length == 1){
// 这是用户窗口中的第一个页面
}
注意 如果页面URL发生变化,则会在历史记录中生成一个新条目。改变URL的散列值(即,把location.hash设置为一个新值)会在这些浏览器的历史记录中增加一条记录。这个行为常被单页应用程序框架来模拟前进和后退。
12.5.2 历史状态管理
现代Web 应用程序开发中最难的环节之一就是历史记录管理。HTML5 为history 对象增加了方便的状态管理特性。
hashchange 会在页面URL 的散列变化时被触发,开发者可以在此时执行某些操作。而状态管理API 则可以让开发者改变浏览器URL 而不会加载新页面。为此,可以使用history.pushState()方法。这个方法接收3 个参数:一个state 对象、一个新状态的标题和一个(可选的)相对URL。例如:
let stateObject = {foo:"bar"};
history.pushState(stateObject, "My title", "baz.html");
pushState()方法执行后,状态信息就会被推到历史记录中,浏览器地址栏也会改变以反映新的相对URL。
可以通过history.state 获取当前的状态对象,也可以使用replaceState()并传入与pushState()同样的前两个参数来更新状态。更新状态不会创建新历史记录,只会覆盖当前状态。例子:
假设 http://mozilla.org/foo.html 执行下面的 JavaScript 代码:
var stateObj = { foo: "bar" };
history.pushState(stateObj, "", "bar.html");
上面这两行的解释可以在 "Example of pushState() method"这个章节找到。然后假设 http://mozilla.org/bar.html 执行下面的 JavaScript 代码:
history.replaceState(stateObj, "", "bar2.html");
这会让URL栏显示 http://mozilla.org/bar2.html, 但是不会加载 bar2.html
页面,甚至不会检查bar2.html 是否存在。