在开始讨论JavaScript之前,有必要先思考一下在Web浏览器中是如何呈现Web页面的。一些呈现静态信息的页面,叫做文档(document)(由于加入了JavaScript,静态页面的信息看上去会动来动去,但信息本身是静态的),相对于文档来说,其他Web页面则感觉上更像是应用。如果需要的话,这些页面可以动态载入新的信息,因此看起来更加图形化,而非文本化,并且它们可以进行离线操作,以及保存数据到本地,以便再次访问时进行状态恢复。此外,还有其他Web页面处于文档和应用的中间,结合了两者的特性。
Window对象是所有客户端JavaScript特性和API的主要接入点。它表示Web浏览器的一个窗口或窗体,并且可以用标识符window来引用它。Window对象定义了一些属性,比如,指代Location对象的location属性,Location对象指定当前显示在窗口中的URL,并允许脚本往窗口里载入新的URL:
// 设置location属性,从而跳转到新的Web页面 window.location = "http://www.oreilly.com/";
Window对象还定义了一些方法,比如
alert()
,可以弹出一个对话框用来显示一些信息。还有setTimeout()
,可以注册一个函数,在给定的一段时间之后触发一个回调:// 等待两秒,然后说hello setTimeout(function() { alert("hello world"); }, 2000);
注意上面的代码并没有显式地使用window属性。在客户端JavaScript中,Window对象也是全局对象。这意味着Window对象处于作用域链的顶部,它的属性和方法实际上是全局变量和全局函数。Window对象有一个引用自身的属性,叫做windowo如果需要引用窗口对象本身,可以用这个属性,但是如果只是想要引用全局窗口对象的属性,通常并不需要用到window。
Window对象还定义了很多其他重要的属性、方法和构造函数。
Window对象中其中一个最重要的属性是document,它引用Document对象,后者表示显示在窗口中的文档。Document对象有一些重要方法,比如
getElementById()
,可以基于元素id属性的值返回单一的文档元素(表示HTML标签的一对开始/结束标记,以及它们之间的所有内容):// 査找 id="timestamp" 的元素 var timestamp = document.getElementById("timestamp");
getElementById()
返回的Element对象有其他重要的属性和方法,比如允许脚本获取它的内容,设置属性值等:// 如果元素为空,往里面插入当前的日期和时间 if (timestamp.firstChild == null) timestamp.appendChild(document.createTextNode(new Date().toString()));
每个Element对象都有style和className属性,允许脚本指定文档元素的CSS样式,或修改应用到元素上的CSS类名。设置这些CSS相关的属性会改变文档元素的呈现:
// 显式修改目标元素的呈现 timestamp.style.backgroundcolor = "yellow"; // 或者只改变类,让样式表指定具体内容 timestamp.className = "highlight";
Window、Document和Element对象上另一个重要的属性集合是事件处理程序相关的属性。可以在脚本中为之绑定一个函数,这个函数会在某个事件发生时以异步的方式调用。事件处理程序可以让JavaScript代码修改窗口、文档和组成文档的元素的行为。事件处理程序的属性名是以单词“on”开始的,用法如下:
// 当用户单击timestamp元素时,更新它的内容 timestamp.onclick = function() { this.innerHTML = new Date().toString(); }
Window对象的onload处理程序是最重要的事件处理程序之一。当显示在窗口中的文档内容稳定并可以操作时会触发它。JavaScript代码通常封装在onload事件处理程序里。下例是onload处理程序的演示,并展示了客户端JavaScript的实例代码,包括査询文档元素、修改CSS类和定义事件处理程序。这个例子的JavaScript代码是放置在HTML的
<script>
标签之内的。注意代码里的一个函数是在另一个函数里定义的。因为事件处理程序的广泛使用,使得嵌套函数在客户端JavaScript中非常普遍。例:显示内容的简单客户端JavaScript <!DOCTYPE html> <html> <head> <style> /* 本页的css样式表 */ .reveal * { display: none; } /* class="reveal"的元素的子元素都不显示 */ .reveal *.handle { display: block;} /* 除了class="handle"的元素 */ </style> <script> // 所有的页面逻辑在onload事件之后启动 window.onload = function() { // 找到所有class名为“reveal”的容器元素 var elements = document.getElementsByClassName("reveal"); for (var i = 0; i < elements.length; i++) { // 对每个元素进行遍历 var elt = elements[i]; // 找到容器中的,"handle"元素 var title = elt.getElementsByClassName("handle")[0]; // 当单击这个元素时,呈现剩下的内容 addRevealHandler(title,elt);} function addRevealHandler(title,elt) { title.onclick = function() { if (elt.className == "reveal") elt.className = "revealed"; else if (elt.className == "revealed") elt.className = "reveal"; } } }; </script> </head> <body> <div classs="reveal"> <hl class="handle">Click Here to Reveal Hidden Text</hl> <p>This paragraph is hidden.It appears when you click on the title.</p> </div> </body> </html>
JavaScript程序可以通过Document对象和它包含的Element对象遍历和管理文档内容。它可以通过操纵CSS样式和类,修改文档内容的呈现。并且可以通过注册适当的事件处理程序来定义文档元素的行为。内容、呈现和行为的组合,叫做动态HTML或DHTML。
Web文档里应当少量地使用JavaScript,因为JavaScript真正的角色是增强用户的浏览体验,使信息的获取和传递更容易。用户的体验不应依赖于JavaScript,但JavaScript可以增强体验,比如通过下面的方式:
- 创建动画和其他视觉效果,巧妙地引导和帮助用户进行页面导航。
- 对表格的列进行分组,让用户更容易找到所需要的。
- 隐藏某些内容,当用户“深入”到内容里时,再逐渐展示详细信息。
在Web文档中使用的JavaScript DHTML特性在Web应用中都会用到,对于Web应用来说,除了内容、呈现和操作API之外,还依赖了Web浏览器环境提供的更基础的服务。
要真正理解Web应用,需要先认识到Web浏览器已经有了很好的发展,现在已经不仅仅是作为显示文档的工具的角色了,而渐渐变成了一个简易的操作系统。想一下,传统操作系统允许组织桌面和文件夹里的图标(表示文件或应用),Web浏览器允许在工具栏和文件夹里组织书签(表示文档和Web应用)。系统可以在一个窗口里运行多个应用;Web浏览器可以在一个标签里显示多个文档。操作系统定义了很多底层网络API、提供绘制图像、保存文件等功能。
谨记Web浏览器是简单操作系统的概念,这样就可以把Web应用定义为用JavaScript访问更多浏览器提供的高级服务(比如网络、图像和数据存储)的Web页面。高级服务里最有名的是XMLHttpRequest对象,后者可以对HTTP请求编程来启用网络。Web应用使用这个服务从服务器获取新信息,而不用重新载入页面。类似这样的Web应用通常叫做Ajax应用,Ajax构成了“Web 2.0”的脊梁。
HTML5标准和相关的标准为Web应用定义了很多其他重要的API。在实现这些API之后,会开启一场Web应用功能的革命。JavaScript增强了Web文档,但是设计良好的文档需要在禁用JavaScript后还能继续工作。Web应用本质上就是 JavaScript程序,后者使用由Web浏览器提供的操作系统类型的服务,并且不用期望它们在禁用浏览器脚本后还能正常工作。