2.4.1 比较操作符
如果想比较两个值是否相等,可以使用等于(==)比较操作符。如果在条件语句的某个条件里使用了单个等号,那么根据相应的赋值操作返回值作为判断条件。
if (a = true) {console.log(true)} // 这里返回值为 true,打印出 true
if (a = false) {console.log(false)} // 这里返回值为 false,代码块里的语句不会执行
3.2 对象:DOM 中的 “O”
“对象” 是一种自足的数据集合。与某个特定对象相关联的变量被称为这个对象的属性,只能通过某个特定对象去调用的函数被称为这个对象的方法。
JavaScript 语言里的对象可以分为三种类型:
- 用户定义对象(user-defined object):由程序员自行创建的对象。
- 内建对象(native object):内建在 JavaScript 语言里的对象,如 Array、Math 和 Date 等。
- 宿主对象(host object):由浏览器提供的对象。
3.4 节点
文档是由节点构成的集合。在 DOM 里有许多不同类型的节点,也有很多类型的 DOM 节点包含着其他类型的节点。
常用的三种节点:元素节点、文本节点和属性节点
3.4.5 获取元素
有 3 种 DOM 方法可获取元素节点,分别是通过元素 ID、标签名和类名来获取。
- getElementById:返回一个给定 id 属性值的元素节点对应的对象。
- getElementsByTagName:返回一个对象数组,每个对象分别对应着文档里有着给定标签的一个元素。
- getElementsByClassName:返回一个具有相同类名的元素的数组(可指定多个类名,只要在字符串参数中用空格分隔类名即可。类名的实际顺序不重要,甚至还带有更多类名也没有关系)。
3.5 获取和设置属性
- getAttribute:返回指定属性名的属性值。它不属于 document 对象,只能通过元素节点对象调用。
- setAttribute:更改属性节点的值。它也只能用于元素节点。
4.4.2 nodeType属性
每一个节点都有 nodeType 属性。nodeType 属性总共有 12 种可取值,但其中仅有 3 种具有实用价值。
- 元素节点的 nodeType 属性值是 1。
- 属性节点的 nodeType 属性值是 2。
- 文本节点的 nodeType 属性值是 3。
5.2 平稳退化
如果正确地使用了 JavaScript 脚本,就可以让访问者在他们的浏览器不支持 JavaScript 的情况下仍能顺利地浏览你的网站。就是说,虽然某些功能无法使用,但最基本的操作仍能顺利完成。
5.2.1 "javascript:" 伪协议
“真”协议用来在因特网上的计算机之间传输数据包,如 HTTP 协议(http://)、FTP 协议(ftp://)等,伪协议则是一种非标准化的协议。"javascript:" 伪协议让我们通过一个链接来调用 JavaScript 函数。
举个栗子:下面通过 "javascript:" 伪协议调用 popUp() 函数:
<a href="javascript:popUp('http://www.example.com/');">Example</a>
这条语句在支持 "javascript:" 伪协议的浏览器中运行正常,较老的浏览器则会去尝试打开那个链接但失败,支持这种伪协议但禁用了 JavaScript 功能的浏览器会什么也不做。
总之,在 HTML 文档里通过 "javascript:" 伪协议调用 JavaScript 代码的做法非常不好。
5.2.2 内嵌的事件处理函数
把事件处理函数作为属性嵌入 HTML 标签
举个栗子:下面通过 onclick 事件处理函数调用 popUp() 函数:
<a href="#" onclick="popUp('http://www.example.com/');return false;">Example</a>
因为在上面的这条 HTML 指令里使用了 return false 语句,这个链接不会真的被打开。把 href 属性的值设置为 “#” 只是为了创建一个空链接,实际工作全部由 onclick 属性负责完成。
很遗憾,这个技巧与用 "javascript:" 伪协议调用 JavaScript 代码的做法同样糟糕,因为它们都不能平稳退化。如果用户已经禁用了浏览器的 JavaScript 功能,这样的链接将毫无用处。
5.2.3 谁关心这个
让那些不支持或禁用了 JavaScript 功能的浏览器也能顺利地访问你的网站真的那么重要吗?
请想象一下,如果那个用户是一个搜索机器人。搜索机器人是一种自动化的程序,它们浏览 Web 的目的是为了把各种网页添加到搜索引擎的数据库里。各大搜索引擎都有类似的程序。目前,只有极少数的搜索机器人能够理解 JavaScript 代码。所以,如果你的 JavaScript 网页不能平稳退化,它们在搜索引擎上的排名就可能大受损害。
举个栗子:具体到 popUp() 函数,为其中的 JavaScript 代码预留出退路很简单:
在链接里把 href 属性设置为真实存在的 URL 地址,让它成为一个有效的链接。
<a href="http://www.example.com/" onclick="popUp(this.href);return false;">Example</a>
所以,在把 href 属性设置为真实存在的 URL 地址后,即使 JavaScript 已被禁用,这个链接也是可用的。这是一个经典的 “平稳退化” 的例子。
5.3.1 结构与样式分离
我们经常会遇到一些几乎每个元素都带有 style 属性的 Web 文档,而这是 CSS 技术最缺乏效率的用法之一。真正能从 CSS 技术获益的方法,是把样式全部转移到外部文件中去。
作为 CSS 技术的突出优点,文档结构与文档样式的分离可以确保网页都能平稳退化。
5.3.2 渐进增强
“标记良好的内容就是一切”
只有正确地使用标记语言才能对内容做出准确的描述。
在给内容加上各种标记后,就可以使用各种 CSS 指令控制内容的显示效果。CSS 指令构成了一个表示层。这个表示层就像是一张透明的彩色薄膜,可以包裹到文档的结构上,使文档的内容呈现出各种色彩。但即使去掉这个表示层,文档的内容也依然可以访问。
所谓 “渐进增强” 就是用一些额外的信息层去包裹原始数据。按照 “渐进增强” 原则创建出来的网页几乎都符合 “平稳退化” 原则。
类似 CSS,JavaScript 和 DOM 提供的所有功能也应该构成一个额外的指令层。CSS 代码负责提供关于 “表示” 的信息,JavaScript 代码负责提供关于 “行为” 的信息。行为层的应用方式与表示层一样。
5.5 向后兼容
正如前面反复强调的那样,你的网站的访问者很可能未启用 JavaScript 功能。此外,不同的浏览器对 JavaScript 的支持程度也不一样。绝大多数浏览器都能或多或少地支持 JavaScript,而绝大多数现代浏览器对 DOM 的支持都非常不错。但比较古老的浏览器却很可能无法理解 DOM 提供的某些方法和属性。因此,即使某位用户在访问你的网站时使用的是支持 JavaScript 的浏览器,某些脚本也不一定能正常工作。
针对这一问题的最简单的解决方案是,检测浏览器对 JavaScript 的支持程度。
5.5.1 对象检测
这个解决方案很容易实现:只要把某个方法打包在一个 if 语句里,就可以根据这条 if 语句的条件表达式的求值结果是 true(这个方法存在) 还是 false(这个方法不存在) 来决定应该采取怎样的行动。这种检测称为对象检测(object detection)。
举个栗子:
window.onload = function () {
if (!document.getElementsByTagName) {
return false;
}
}
虽然只是一条简单的 if 语句,但它可以确保那些 “古老的” 浏览器不会因为我的脚本代码而出问题。这么做是为了让脚本有良好的向后兼容性。因为我在给网页添加各有关行为时始终遵循了 “渐进增强” 的原则,所以可以确切地知道我添加的那些都能平稳退化,我的网页在那些 “古老的” 浏览器里也能正常浏览。那些只支持一部分 JavaScript 功能但不支持 DOM 的浏览器仍可以访问我的网页的内容。
5.6.1 尽量少访问 DOM 和尽量减少标记
访问 DOM 的方式对脚本的性能会产生非常大的影响。不管什么时候,只要是查询 DOM 中的某些元素,浏览器都会搜索整个 DOM 树,从中查找可能匹配的元素。更好的办法是把第一次查询的结果保存在一个变量中,然后重用该结果。
在多个函数都会取得一组类似元素的情况下,可以考虑重构代码,把搜索结果保存在一个全局变量里,或者把一组元素直接以参数形式传递给函数。
另一个需要注意的地方,就是要尽量减少文档中的标记数量。过多不必要的元素只会增加 DOM 树的规模,进而增加遍历 DOM 树以查找特定元素的时间。
5.6.2 合并和放置脚本
包含脚本的最佳方式就是使用外部文件,因为外部文件与标记能清晰地分离开,而且浏览器也能对站点中的多个页面重用缓存过的相同脚本。
把多个脚本文件合并到一个脚本文件中,可以减少加载页面时发送的请求数量。
脚本在标记中的位置对页面的初次加载时间也有很大影响。位于 <head> 块中的脚本会导致浏览器无法并行加载其他文件(如图像或其他脚本)。一般来说,根据 HTTP 规范,浏览器每次从同一个域名中最多只能同时下载两个文件。而在下载脚本期间,浏览器不会下载其他任何文件,即使是来自不同域名的文件也不会下载,所有其他资源都要等脚本加载完毕后才能下载。
把所有 <script> 标签都放在文档的末尾,</body> 标记之前,就可以让页面变得更快。
5.6.3 压缩脚本
所谓压缩脚本,指的是把脚本文件中不必要的字节,如空格和注释,统统删除,从而达到 “压缩” 文件的目的。
多数情况下,你应该有两个版本,一个是工作副本,可以修改代码并添加注释;另一个是精简副本,用于放在站点上。通常,为了与非精简版本区分开,最好在精简副本的文件名中加上 min 字样。
举个栗子:
<script src="scripts/scriptName.min.js"></script>
推荐几个有代表性的代码压缩工具:
- Douglas Crockford 的 JSMin
- 雅虎的 YUI Compressor
- 谷歌的 Closure Compiler
6.8 DOM Core 和 HTML-DOM
列举几个常用的 DOM 方法:
- getElementById
- getElementsByTagName
- getElementsByClassName
- getAttribute
- setAttribute
这些方法都是 DOM Core 的组成部分。它们并不专属于 JavaScript,支持 DOM 的任何一种程序设计语言都可以使用它们。它们的用途也并非仅限于处理网页,它们可以用来处理任何一种标记语言(比如 XML)编写出来的文档。
HTML-DOM 提供了许多描述各种 HTML 元素的属性。
举个栗子:
document.getElementsByTagName('form')
可简化为:
document.forms
element.getAttribute('src')
可简化为:
element.src
这些方法和属性可以相互替换。同样的操作既可以使用 DOM Core 来实现,也可以使用 HTML-DOM 来实现。HTML-DOM 代码通常会更短,必须提醒一下,它们只能用来处理 Web 文档。
7.4.1 XMLHttpRequest 对象
Ajax 技术的核心就是 XMLHttpRequest 对象。这个对象充当着浏览器中的脚本(客户端)与服务器之间的中间人的角色。以往的请求都由浏览器发出,而 Javascript 通过这个对象可以自己发出请求,同时也自己处理响应。
XMLHttpRequest 对象有许多的方法。其中最有用的是 open 方法,它用来指定服务器上将要访问的文件,指定请求类型:GET、POST、或 SEND。这个方法的第三个参数用于指定请求是否以异步方式发送和处理。
onreadystatechange 是一个事件处理函数,它会在服务器给 XMLHttpRequest 对象返回响应的时候被触发执行。
服务器在向 XMLHttpRequest 对象返回响应时,该对象有许多属性可用,浏览器会在不同阶段更新 readyState 属性的值,它有 5 个可能的值:
- 0 表示未初始化
- 1 表示正在加载
- 2 表示加载完毕
- 3 表示正在交互
- 4 表示完成
只要 readyState 属性的值变成了 4,就可以访问服务器发送回来的数据了。
访问服务器发送回来的数据要通过两个属性完成。一个是 responseText 属性,这个属性用于保存文本字符串形式的数据。另一个属性是 responseXML 属性,用于保存 Content-Type 头部中指定为 “text/xml” 的数据,其实是一个 DocumentFragment 对象。你可以使用各种 DOM 方法来处理这个对象。而这也正是 XMLHttpRequest 这个名称里有 XML 的原因。
注意:在使用 Ajax 时,千万要注意同源策略。使用 XMLHttpRequest 对象发送的请求只能访问与其所在的 HTML 处于同一个域中的数据,不能向其他域发送请求。
网友评论