《JavaScript 高级程序设计》笔记(3) —— BOM 及客户端检测
BOM、客户端检测
第 8 章 BOM
window 对象
window 对象表示浏览器的一个实例。
全局作用域 : window 对象是 ECMAScript 中规定的 Global 对象,是通过 JavaScript 访问浏览器窗口的一个接口。
window 对象和 全局对象差别 : 定义在 window 上的变量可以通过 delete 操作符删除,而定义全局变量不可以;访问不存在的全局变量会报错,查询 window 属性不会。
窗口关系及框架 : 每个框架都有自己的 window 对象,保存在 frames 集合中,使用索引或 name 属性访问对应的 window 对象。top 对象始终指向最外层的框架;parent 始终指向当前框架的直接上层框架;self 始终指向 window。
窗口位置 :
- IE、Safari、Opera、Chrome 使用 screenLeft 和 screenTop
- Firefox、Safari、Chrome 使用 screenX 和 screenY
- 移动使用 moveTo( , ) 和 moveBy( , )
窗口大小 :
-
IE9+、Safari、Opera、Chrome、Firefox 提供 innerWidth、innerHeight【减去边框宽度】,outerWidth、outerHeight。 IE9+、Safari、Firefox 的 outerWidth、outerHeight 返回浏览器本身窗口的尺寸, Opera 返回页面视图容器的大小, Chrome 中 innerWidth、innerHeight,outerWidth、outerHeight 返回相同的值
-
IE、Safari、Opera、Chrome、Firefox 中,document.documentElement.clientWidth 和 document.documentElement.clientHeigth 保存了页面视口的信息, 在IE6中,以上标准模式有效,在混杂模式下,采用 document.body.clientWidth 和 document. body.clientHeigth, 混杂模式下的 Chrome,以上四种都可以。
-
resizeTo(a,b) 调整到a*b ; resizeBy(c,d) 调整到 a+c,b+d
导航和打开窗口 :
- window.open() 打开一个特定的 url 或者信息浏览器窗口。里面可传四个参数,要加载的 url、窗口目标(可以是一个 target 框架名或者 _self、_blank、_parent、_top)、一个特性字符串(不打开新窗口,忽略这个,打开的话,可设置 fullscreen[yes,no,IE]、heigth、width、left、rigth、scrollbar…)、表示新页面是否取代李兰器历史记录当前加载页面的布尔值 var xxx=window.open(…….); xxx.opener == window window.close(); ======xxx.closed 浏览器内置的屏蔽程序阻止弹出窗口,window.open()可能为null
间歇调用和超时调用
超时调用 : var time = setTimeout(代码字符串或者函数,1000); clearTimeout(time); 间歇调用 : var time = setInterval(代码字符串或者函数,1000); clearInterval(time);
系统对话框
系统对话框:alert()、confirm()、prompt()
location 对象
location 既是 window 的对象的属性,也是 document 的对象的属性。
属性 : hash、host、hostname、href、pathname、port、protocol、search
查询字符串参数
位置操作
使用 assign(URL) 方法。 改变 location.href 或 window.location,也会调用 assign() 方法。 改变 location 其它属性也可以改变当前加载的页面。
replace(URL) 方法不会再历史记录中生成新的记录。
reload() 重新加载当前页面。location.reload() 可能从缓存中加载,location.reload(true) 从服务器加载。
navigator 对象
…
screen 对象
…
history 对象
- 后退 : history.go(-1)/back()
- 前进 : history.go(1)/history.go(2)/history.go(URL)/forward()
第 9 章 客户端检测
能力监测(特性检测)
能力监测用于识别浏览器的能力
// IE5 之前使用 document.all[id], 后来的使用 document.getElementById(id)
if (object.prototypeInQuestion) {
// 使用 object.prototypeInQuestion
}
- 两个重要概念 : 先检测达成目的的最常用的特性;必须测试实际要用到的特性。
- 在可能的情况下,尽量使用 typeof 进行能力检测。
- 能力检测不是浏览器检测
怪癖检测
怪癖检测用于识别浏览器的特殊行为(bug)
// 检测 IE8- 如果某个实例属性与 [[Enumerable]] 标记为 false 的某个原型属性同名,该实例属性将不会出现在 for-in 循环中
var hasDontEnumQuirk = function () {
var o = { toString : function () {} };
for (var prop in o) {
if (prop == "toString") {
return false;
}
}
return true;
}();
用户代理检测
通过检测用户代理字符串来确定实际使用的浏览器。优先级排在能力检测和怪癖检测之后。
电子欺骗
navigator.userAgent 属性
完整的用户代理字符串检测脚本 :
var client = function () {
// 呈现引擎
var engine = {
ie : 0,
gecko : 0,
webkit : 0,
khtml : 0,
opera : 0,
// 完整的版本号
ver : null
};
// 浏览器
var browser = {
// 主要浏览器
ie : 0,
firefox : 0,
safari : 0,
konq : 0,
opera : 0,
chrome : 0,
// 具体的版本
ver : null
};
// 平台、设备和操作系统
var system = {
win : false,
mac : false,
xll : false,
// 移动设备
iphone : false,
ipod : false,
ipad : false,
ios : false,
android : false,
nokiaN :false,
winMobile : false,
// 游戏系统
wii : false,
ps : false
};
// 检测呈现引擎及浏览器
var ua = navigator.userAgent;
if (window.opera) {
engine.ver = window.opera.version();
engine.opera = parseFloat(engine.ver);
} else if (/AppleWebKit\/(\S+)/.test(ua)) {
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
// 确定是 Chrome 还是 Safari
if (/Chrome\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.chrome = parseFloat(browser.ver);
} else if (/Version\/(S+)/.test(ua)) {
browser.ver = RegExp["$1"];
borwser.safari = parseFloat(browser.ver);
} else {
//近似的确定版本号
var safariVersion = 1;
if (engine.webkit < 100) {
safariVersion = 1;
} else if (engine.webkit < 312) {
safariVersoin = 1.2;
} else if (engine.webkit < 412) {
safariVersion = 1.3;
} else {
safariVersion = 2;
}
browser.safari = browser.ver = safariVersion;
}
} else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) {
engine.ver = RegExp["$1"];
engine.khtml = parseFloat(engine.ver);
} else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {
engine.ver = RegExp["$1"];
engine.gecko = parseFloat(engine.ver);
//确定不是Firefox
if (/Firefox\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.firefox = parseFloat(browser.ver);
}
} else if (/MSIE ([^;]+)/.test(ua)){
engine.ver = browser.ver = RegExp["$1"];
engine.ie = browser.ie = parseFloat(engine.ver);
}
// 检测浏览器
browser.ie = engine.ie;
browser.opera = engine.opera;
// 检测平台
var p = navigator.platform;
system.win = p.indexOf("Win") == 0;
system.mac = p.indexOf("Mac") == 0;
system.xll = (p == "X11") || (p.indexOf("Linux" == 0));
// 检测 Windows 操作系统
if (system.win) {
if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) {
if (RegExp["$1"] == "NT") {
switch (RegExp["$2"]) {
case "5.0":
system.win = "2000";
break;
case "5.1":
system.win = "XP";
break;
case "6.0":
system.win = "Vista";
break;
case "6.1":
system.win = "7";
break;
default:
system.win = "NT";
break;
}
} else if (RegExp["$1"] == "9x") {
system.win = "ME";
} else {
system.win = RegExp["$1"];
}
}
}
// 移动设备
system.iphone = ua.indexOf("iPhone") > -1;
system.ipod = ua.indexOf("iPod") > -1;
system.ipad = ua.indexOf("iPad") > -1;
system.nokiaN = ua.indexOf("NokiaN") > -1;
// windows mobile
if (system.win == "CE") {
system.winMobile = system.win;
} else if (system.win = "Ph") {
if (/Windows Phone OS (\d+.\d+)/.test(ua)) {
system.win = "Phone";
system.winMobile = parseFloat(RegExp["$1"]);
}
}
// 检测 iOS 版本
if (system.mac && ua.indexOf("Mobile") > -1) {
if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) {
system.ios = parseFloat(RegExp.$1.replace("_", "."));
} else {
system.ios = 2; // 不能真正检测出来, 所以只能猜测
}
}
// 检测 Android 版本
if (/Android (\d+\.\d+)/.test(ua)) {
system.android = parseFloat(RegExp.$1);
}
// 游戏系统
system.wii = ua.indexOf("Wii") > -1;
system.ps = /playstation/i.test(ua);
// 返回这些对象
return {
engine : engine,
browser : browser,
system : system
};
}();