第十一蟑介绍了window对象及其客户端javascript所扮演的核心角色:它是客户端javascript程序的全局对象。本章介绍window对象的属性和方法,这些属性定义了不同的API,但是只有一部分实际上和浏览器窗口相关。window对象是以窗口命名的。
1节展示如何使用setTimeout()和setInterval()来注册一个函数,并在指定的时间后调用它。
2节讲述如何使用location属性来获取当前显式文档的URL和载入新的文档
3节介绍history属性,并展示如何在历史记录中向前和向后移动
4节展示如何使用navigator获取浏览器的厂商和版本信息,如何使用screen属性来查询窗口的尺寸
5节展示如何使用alert()、prompt()、confirm()来显示简单的文本对话框,以及如何使用showModalDialog()显示HTML对话框
6节讲解如何使用onerror处理方法,这个方法在未补货javascript异常发生时调用
7节讲述HTML元素的ID和name作为window对象的属性来使用
8是一个很长的节,讲解如何打开和关闭浏览器。以及如何编写在多个窗口和嵌套窗体中的javascript 代码
1.计时器
setTimeout()和setIterval()可以用来注册在指定的时间之后,单词或重复调用的函数。因为它们都是客户端javascript中的重要全局函数,所以定义为window对象方法,但作为通用函数,其实并不会对窗口做什么事情。
window对象的setTimeout()方法用来实现一个函数在指定的毫秒后运行。setTimeout返回一个值,这个值可以传给clearTimeout()用于取消这个函数的执行。
SetInterval()和setTimeout()一样,只不过这个函数会在指定的毫秒数的间隔里重复调用:
setInterval(updataClock,60000);//,每隔60秒调用一次updataClock函数
和setTimeout()一样,setInterval()函数也返回一个值,这个值可以传递给clearInterval(),用于取消后续函数的调用。
下面的例子定义的函数会在指定的时间之后,开始重复调用某个函数,然后在过了一段时间后取消函数的调用。该例子演示了setTimeout、setInterval、clearInterval的用法
/**定时器应用函数 * 安排函数f()在未来的调用模式 * 在等待了若干时间后调用f() * 如果设置了interval并没有设置end参数,则f()的调用不会停止 * 只有制定了f(),才会从start=0时刻开始 * 注意,调用invoke()不会阻塞,会立即返回 * */ function invoke(f, start, interval, end) { if (!start) start = 0;//默认设置为0 if(arguments.length <=2)//单次调用模式 setTimeout(f,start);//start秒后调用f else{ setTimeout(repeat,start);//若干秒后调用f() function repeat(){ var h = setInterval(f,interval);//循环调用f() //在end结束后调用,嵌套是end已经定义了 if(end) setTimeout(function(){clearInterval(h);},end); } } }
由于历史原因,setTimeout()和setInterval()第一个参数可以作为字符串传入。如果这么做,那这个字符串会在指定的超时时间或间隔之后求值(相当于执行eval()).除了前两个参数之外,HTML5规范还允许setTimeout()和setInterval()传入额外的参数,并且在调用函数的时候把这些参数传过去。
如果以0毫秒时间调用setTimeout,那么指定的函数不会立刻执行。相反会把它放到队里中,等到前面处于等待状态的事件处理程序完全完成之后,再立刻调用它。
2.浏览器的定位和导航
window对象的location属性引用的是Location对象,它表示该窗口中当前文档的URL,并定义了方法使创口引用到Location对象。
window.location === document.location; //=>true 总是返回true
Document对象也有一个URL属性,是文档首次载人后保存该文档的URL静态字符串。如果定位到文档中的片段标识符(如#table-of-contens),Location对象会做响应更新,而document.url属性却不会改变。
i.解析url
window对象的location属性引用是Location对象,表示当前显示的的文档的URL。Location对象的href属性是一个字符串。Location对象的toString()方法返回href属性的值,因此会在隐式调用toString()情况下,使用location代替Location.href
var d = location.href; var c = location.toString(); console.log(d === c)
这个对象的其它属性,protocol,host,hostname,port,pathname和search分别表示URL的各个部分。它们称为"URL分解",同时被Link对象(通过HTML文档中的a和<area>元素创建)支持,参阅本书的第四部分,Location和Link项获取详细信息。
Location对象的hash和seerch比较有意思。hash表示URL中的“片段标识符 #xx”部分,search返回问好之后的URL,这部分一般是某种类型的查询字符串。
下面的例子展示了一个通用函数urlArgs()定义,可以用这个函数将参数从URL的search属性中提取出来。该例子用到了decodeURIComponent(),后者是在客户端Javascript定义的全局函数(参加本书第三章部分中的Global获取详细内容)。
/** *这个函数来解析来自URL的查询中串中的name=value参数 * 它将name=value对象存储在一个对象的属性中,并返回该对象,这样使用它 * * var args = urlArgs();//从URL中解析参数 * var q = args.q ||"";//如果参数定义的话就使用它,否则使用默认值。 * var n = args.n?parseInt(args.n):10 **/ function urlArgs() { var args = {}; //空对象 var query = location.search.substring(1); //?后的值 var pairs = query.split("&"); for (var i = 0; i < pairs.length; i++) { //对于每个片段 var pos = pairs[i].indexOf(‘=‘); if (pos == -1) continue; //如果没有找到的话,跳过 var name = pairs[i].substring(0, pos); //提取name var value = pairs[i].substring(pos + 1); //提取value value = decodeURIComponent(value); //对value进行解码 args[name] = value; } return args; }
ii.载入新的文档
Location对象的assign()方法可以使窗口载入并显示你指定的url文档。replace()方法也类似,但它在载入新的文档之前会从浏览历史把当前文档删除。如果脚本无条件的载入一个新的文档,replace()方法是可能比assgin()方法更好的选择。否则,后退 按钮会使用浏览器带回原始文档。而相同的脚本则会再次载入新文档。如果检测到用户浏览器不支持某些特性来显示功能齐全的版本,可以这样做:
//如果浏览器不支持XMLHttpRequest对象 //则将其重定向到一个不需要Ajax的静态页面 if (XMLHttpRequest) location.replace("aa.html");
除了assign()和replace()方法,Location对象还定义了reload()方法,后者可以让浏览器重新载入当前文档。
传统的方法一般是这样做
location = "http://a.com"; location = "page.html";
纯粹的片段标识符也是url的一种类型,可以这样定义
location = "http://a.com#cll"; location = "page.html#top";
Location对象的URL是可写的,对它们重新赋值会改变URL的位置,导致浏览器载入新的文档(如果是hash属性,则定位到片段标识符)
location.search = "?page=" + (pagename+1);//载入新的页面
3.浏览历史
window对象的history属性是引用该窗口的History对象。History对象是用来把窗口的浏览历史用文档和文档状态列表的形式表示。History对象的length属性表示浏览意思列表的数量元素,处于安全考虑,脚本不能访问已经保存的URL.
history对象的back()和forward()方法与浏览器的“后退”和“前进”按钮一样。它们可以往前后跳转一格,第三个方法go(),接受一个参数,可以像前(正参数)向后(幅参数)跳过任意个页面。
history.go(-2); //向后两个历史记录,相当于后退按钮两次
如果窗口包含多个子窗口(比如iframe见本文8.ii节),子窗口的历史会按照穿插主窗口的历史中。
现代的web应用可以不通过载入新的文档而动态的改变自身内容。这么做希望用户能用“后退”和“前进”按钮在这些动态创建应用状态之间跳转。html5将这些技术标准(18章2节)。
在现实的工作中,那些需要以前的HTML5历史管理项目中,开发者会使用一些现成 解决方法(因为之前历史管理是个复杂的难题),很多框架都实现了这些功能。例如jQuery的history插件。也有一些单独的类库。RSH(Really Simple History)是其中一个比较流行的示例。(20章2节会有关于html5的历史管理)
4.浏览器和屏幕信息
本节介绍window对象的navigator和screen属性,它们分别引用的是Navigator和Screen对象,这些对象信息允许脚本根据环境定制的行为。
浏览器有一定的嗅探价值。这样的一种情况是,当需要解决某个浏览器特定的bug时,Navugator对象有4个属性提供关于运行中的浏览器的版本信息。并可以使用这些属性就行嗅探。
i.Nagvigator
appName
web浏览器的全称,IE中,它显示“Microsoft Internet Exploer”.在firefox中,该属性就是“Netscape”,在其它浏览器中也是(为了兼容现在的浏览器嗅探码)。
appVersion
此属性通常以数字开始,并跟随浏览器开发商和版本信息等详细字符串。字符串的前边通常是4.0或者5.0,表示它是第4还是第5代兼容的浏览器。appVersion没有标准格式。所有没有办法判断浏览器的类型
userAgent
浏览器在它的User-Agent HTTP头部发送的字符串。这个属性通常包含所有appVersion信息,并且常常包含其它细节。和appVersion一样,它也没有标准格式。由于这个属性包含绝大部分信息,因此,浏览器嗅探代码通常使用它。
platform
在其上运行的浏览器的操作系统(可能是硬件的字符串)。
下面的例子展示了使用正则表达式(来自jQuery)从navigator.userAgent抽取浏览器的版本和名称方法代码。
/* 使用naVigator.userAgent来进行浏览器嗅探 */ //为客户端嗅探定义browser.name和browser.version,这里使用了jQuery1.41的代码 //name和number都是字符串,对浏览器的输出结果不一样,检测的结果如下 //‘webkit‘:safari或chrome,版本号是WebKit的版本号 //‘opera‘ Opear 版本号就是软件的把嫩好 //"mozilla" Firefox或者基于gecko内核的浏览器,版本号是Gecko的版本 //msie IE+版本号 var browser = (function() { var s = navigator.userAgent.toLowerCase(); var match = /(webkit)[ \/]([\w.]+)/.exec(s) || /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(s) || /(msie)([\w.]+)/.exec(s) || !/compatible/.test(s) && /(mozilla)( ? : .* ? rv : ([\w.] + )) ? /.exec(s)||[]; return{name:match[1]||"",version:match[2]||"0"}; }());
另外一种
var info = {}; info.browser = function() { ua = navigator.userAgent.toLowerCase(); var rwebkit = /(webkit)[ \/]([\w.]+)/; var ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/; var rmsie = /(msie) ([\w.]+)/; var rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/; var match = rwebkit.exec(ua) || ropera.exec(ua) || rmsie.exec(ua) || ua.indexOf("compatible") < 0 && rmozilla.exec(ua) || []; return { name: match[1] || "", version: match[2] || "0" }; }(); console.log(info.browser)
处理浏览器厂商和版本信息的属性之外,Navigator对象还包含一些杂项属性和方法。以下是一些标准化的属性以及广泛应用但未标准的属性
OnLine
navigator.onLine是表示是否浏览器是否连接到网络
geolocation
navigator.geolocation对象拥有确定用户地址位置信息的接口,参加20.1章节细节
javaEnabled
navigator.javaEnabled是一个非标准的方法,当浏览器能运行java小程序时返回true
cookieEnabled
navigator.cookieEnabled也是一个非标准方法,如果浏览器可以永久保存cookie时,返回true,而cookie配置“视具体情况而定”时,可能不返回正确的值。
ii.Screen对象。
window对象的screen属性。它提供有关窗口的大小和可用颜色的数量和信息。属性width和heigth指定是以小苏为单位的窗口大小,属性availWidth和availHeiht指是实际可用的显示大小。属性colorDepth是值显示的BPP值,典型的值有16,24,32
window.screen属性和它引用的screen对象都是非标准但广泛实现的。可用用screen对象来确定web是否运行在一个小的屏幕设备上,如果屏幕有限,是否要选用更小的字体和图片等。
5.对话框
window对象提供了三个方法向用户显示简单点对话框,alert(),confirm()要求用户单击确定或取消,返回一个布尔值,prompt()同样也显示一条消息,等待用户输入字符串,并返回那个字符串。下面的代码全用了这三种方法:
do { var name = prompt("你的名字"); var correct = confirm("你输入了" + name + "\n" + "oK确认,chancel取消"); } while (!correct) alert("hello" + name);
尽管alert(),confirm()和prompt()都容易使用,但是良好的设计都需要有节制的使用它们。如今,唯一常见的就是使用它们调试,查看变量输出的结果是什么。
注意,这些对话框中显示的文本是纯文本,只能使用空格,换行符和各种标点符号来格式化这些对话框。
confirm()和prompt()都会产生阻塞,也就是说再关掉它们所显示的对话框之前,它们不返回,也会停止载入,知道用户响应位置。大多数浏览器里,alert()也会产生阻塞,等待用户关闭关闭对话框,但不总是这样,完整的的细节请参考第四部分的Window.alert()/Window.confirm()、和window.prompt()方法。
除了window的alert()、confirm()和prompt()方法,还有更复杂的方法showModalDialog(),显示一个包含HTML格式的模态对话框(模态对话框就是弹出来后只能点击当前的对话框的内容,底下的页面不能操作)。当窗口关闭后,window.returnValue属性的值就是此方法的返回值。对话框的HTML内容往往必须包含用来设置returnValue的“确认”按钮,如果需要则调用window.close(12.8.i)
下面的例子是一个适用于showModalDialog()的html文件,代码顶部注释包含了showModalDialog()的样例。对话框里显示的大量文本都来自showModalDialog()第二个参数,而不是写死在html中。
<!-- /*使用showModalDialog()方法来显示出对话框*/ 这个html不是独立的,这个文件由showModalDialog()调用 它希望window.dialogArguments是一个由字符串组成的数组,数组的一个元素放在对话框的顶部,剩下的每个元素是每行的输入框的标识 当单击确定时,返回一个数组,这个数组是每个输入框的值组成 使用这样的代码开确定: var p = showModalDialog("multiprompt.html", ["请输入3d坐标","x","y","z"], "dialogwidth:400;dialogheight:300;resizable:yes"); --> <form> <fieldset id="fields"></fieldset> <!--对话框正文部分--> <div style="text-align: center;"> <button onclick="okay()">确定</button> <!--设置返回值和关闭事件--> <button onclick="cancel()">取消</button> <!--关闭时不带任何返回值--> </div> <script type="text/javascript"> //创建对话框主题部分,在fieldset中显示出来 var args = dialogArguments; var text = "<legend>" + args[0] + "</legend>"; for (var i = 1; i < args.length; i++) text += "<label>" + args[i] + ":<input id = ‘f" + i + "‘></label><br>"; document.getElementById("fields").innerHTML = text; //直击关闭这个对话框,不设置返回值 function cancel() { window.close(); } //读取输入框的值,然后设置一个返回值,之后关闭 function okay() { window.returnValue = []; //返回一个数组 for (var i = 1; i < args.length; i++) //设置输入框的元素 window.returnValue[i - 1] = document.getElementById("f" + i).value; window.close(); //关闭对话框,使用showModealDialog()返回 } </script> <form>
6.错误处理
window对象对象的onerror属性是一个事件处理程序,当未捕获的异常传播到调用栈上时就会调用它,并把错误消息输出到浏览器的javascript控制台上。如果给这个属性赋值一个函数,那么只要这个窗口中发生了javascript错误,就会调用该函数,即它成为了窗口的错误处理程序。
由于历史原因,事件处理函数调用通过三个字符串参数,而不是通过传递一个事件对象。(其它客户端对象的onerror处理程序所需要的错误条件是不一样的,但是它们都是正常的事件处理程序,这个函数只需传入一个事件对象。)window.onerror的第一个参数是描述错误的一条消息。第二个参数是一个字符串,它存放引发错误的javascript代码所在文档的 url.第三个参数是引发错误的行数。
除了这三个参数外,onerror处理程序的返回值也很重要。如果onerror处理程序返回false,它通知浏览器事件程序已经处理了错误,不需要其他操作。换句话说,浏览器不应该显示它自己的错误消息。由于历史原因,Firefox里的错误程序必须返回true表示它已经处理了错误
onerror处理程序是很早期的javascript产物,那时候语言核心不包含try/catch异常处理语句。现在的代码已经很少使用它。但是在开发阶段,你可能需要定义一个错误处理程序,当错误发生时,显式的通知自己。
window.onerror = function(msg, url, line) { alert("出错了:\n" + msg + "\n 地址:" + url + "\n行号:" + line); return true; //屏蔽系统事件 }
(本文未完节,您可以关注上一章:第十一章:WEB浏览器中的javascript)
下面将更新:
7.作为window对象属性的文档元素