什么是 JavaScript?你该如何执行它
什么是 JavaScript?你该如何执行它?
JavaScript 是一种基于文本的程序设计语言,在被执行之前不需要进行任何转换。其它程序设计语言比如 Java 和 C++ 都需要先进行编译,才能成为可执行文件,而 JavaScript 可以通过一种用来解释代码的程序立即被执行,这种程序叫做解析器(几乎所有的 web 浏览器都包含有 JavaScript 解析器)。
为了在浏览器中执行 JavaScript,你有两个选择——要么将其放在 HTML 文档中任意位置的 script 元素内部,要么将其放在一个外部 JavaScript 文件(其扩展名为 .js)中,然后在 HTM L文档内部用一个带有 src 属性的空的 script 元素来引用该外部文件。本文对这两种方法都有讨论。
最简单的在 HTML 页面中包含 JavaScript 的方法可能如下:
<script> var x = 3; alert('hello there, I am JavaScript - x is '+x);</script>你可以将这段代码放在你的文档内的任意位置,这样就可以执行这段代码了。但有的地方比起其它地方来明显要好得多——关于这一点的具体建议请参见 JavaScript 该放在哪儿部分。
在未来的 web 页面上可能会有若干不同类型的脚本,所以最好为你的脚本添加一个 MIME 类型:
<script type="text/javascript"> var x = 3; alert('hello there, I am JavaScript - x is '+x);</script>注意:你会发现在网上有些脚本带有 language="javascript" 属性。这种使用方法不属于任何标准,而且完全不起任何效果的;你要是能删的话就把它们都删掉好了。这种用法是过去的做法,那时 VBScript 在 web 页面上的使用还很流行。然而现在 VBScript 的使用已经销声匿迹了,因为它只在 IE 中才能起效。
过去我们需要把 JavaScript 写成 HTML 注释形式,以防止浏览器直接将 JavaScript 代码作为 HTML 显示出来。不过现在你不用再为此费心了,因为现在只有那些非常老旧的浏览器才会这么做。如果你的 DOCTYPE 用的是严格型的 XHTML ,那么任何 JavaScript 就都得放在 CDATA 数据块中,这样它才能生效(不必操心这是为什么——在你目前的学习阶段中,这个原因并不是很重要):
<script type="text/javascript">/* <![CDATA[ */ var x = 3; alert('hello there, I am JavaScript - x is '+x);/* ]]> */</script>不过,对于严格型的 XHTML 文档来说,最好还是不要在其中嵌入任何 JavaScript ,而应该将它们放在一个外部文档中。
链接到外部 JavaScript 文件要链接到一个外部 JavaScript 文件(该文件可以是在同一台服务器上,也可以是在互联网上任意之处),你只需在你的 script 元素中加入一个 src 属性即可:
<script type="text/javascript" src="myscript.js"></script>
当浏览器在某个页面中遇到该元素时,就会加载并执行 myscript.js 文件。如果你设置了 src 属性,那么在该 script 元素内部的任何内容都将被忽略。下面的示例将加载 myscript.js 文件,并执行该文件内部的代码,但却根本不会执行 script 元素内的 alert 。
<script type="text/javascript" src="myscript.js">
alert('I am pointless as I won\'t be executed');
</script>
将你的代码放在外部 JavaScript 文件中有很多好处:
你可以将同一个 JavaScript 功能应用到若干 HTML 文档中去,而维护却依然十分容易:如果需要改变该功能的话,你只需修改一个文件就可以了。你的 JavaScript 可以被浏览器缓存。缓存的意思是指浏览器将复制一份你的 JavaScript ,并将其保存在浏览你网站的访问者的计算机里。下次该用户加载该脚本的时候就不再需要从你的服务器下载了,他可以直接从自己的计算机中获取——因此载入速度会快得多。如果你要修改自己的脚本的话,很容易就能找到它,从而避免了扫描长长的 HTML 文档来查找需要修改的地方。由于调试工具或错误控制台会告诉你哪个文件中包含错误,而且还可以准确地报告出错的代码行号,错误调试也变得更容易了。你可以往一个文档中添加任意数目的 JavaScript 文件,但在你开始这么干之前还有几件事情要考虑。
JavaScript 和浏览器性能将大量的 JavaScript 分成不同的文件,每份文件每次处理一项任务,对于保持功能维护的简便和快速漏洞修复来说这是一个极好的办法。比如说你可能会有像下面这样的若干脚本块:
<script type="text/javascript" src="config.js"></script><script type="text/javascript" src="base.js"></script><script type="text/javascript" src="effects.js"></script><script type="text/javascript" src="validation.js"></script><script type="text/javascript" src="widgets.js"></script>这种做法在开发方面的优点却被它在性能方面的负面影响削弱了。虽然这种情况在不同的浏览器上有轻微的差别,但在最坏的情况中(令人遗憾的是这种情况发生在最常用的浏览器中)会发生下面的情况:
浏览器每遇到一个script 元素,都会停止渲染(显示)该文档。然后浏览器会加载在 src 属性中定义的 JavaScript 文件(如果你要用的脚本位于另一台服务器上的话,你还得等待浏览器找到那台服务器)。然后浏览器将在访问下一个脚本之前先执行这一脚本。以上种种意味着你网站的显示将变得缓慢,直到你页面中包含的所有脚本都经历完上述步骤为止。对于你的访客来说,这可是会非常糟糕的。
解决这个问题的办法之一是使用后端脚本,根据你所使用的所有文件来创建一个单独的文件。通过这种办法你就既可以保持维护的简便性,同时又可以减少自己网页在显示时的延迟。网上有许多完成此任务的后端脚本——其中有一个是用PHP写的,可从 Ed Eliot 获取此脚本。
显示上的延迟还限定了你该将自己的JavaScript放在文档中的什么地方。
JavaScript 该放在哪儿从技术上来讲,你可以将 JavaScript 放在文档内的任意地方。你要做的决定就是,在性能与开发方便之间进行权衡,并确保你用来增强页面功能的 JavaScript 能够立刻产生效果。
传统的脚本放置最优方法是放在文档的 head 之内:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"><html lang="en-en"> <head>?<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />?<title></title>?<script type="text/javascript" src="myscripts.js"></script></head><body><!-- lots of HTML here --></body></html>这种做法的好处在于脚本的位置是可预测的——开发者知道该到何处去找它们。这种做法还有一个优点就是可以确保在文档显示之前,所有的 JavaScript 都已被加载并执行。
而这种方法的缺点则在于,你的脚本会延迟文档的显示,而且该脚本无权使用文档中的 HTML 。因此你就只得延迟所有会改变该文档 HTML 的脚本的执行,直到 HTML 文档加载完成为止。通过 onload 事件处理器或各种各样的 DOMready 或 contentAvailable 技术可以实现这一点——当然,它们都不是无懈可击的,而且其中绝大多数都依赖于特定的浏览器特性。
性能优化专家们最近开始提倡将 JavaScript 放在 body 的末尾:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"><html lang="en-en"> <head>?<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />?<title></title></head><body><!-- lots of HTML here --><script type="text/javascript" src="myscripts.js"></script></body></html>这种做法的好处是可以不会延迟 HTML 的显示,而且还意味着任何你想要用 JavaScript 来修改的 HTML 都已经是可用的了。
这种方法的缺点之一是此方法目前还不太常用,因此可能会使维护你的代码的开发师感到困惑。另一个更严重的缺点是 HTML 在你的 JavaScript 被加载之前就变得可用了。虽然这也许正是你想要达到的效果,但它同时也意味着访问者在你通过 JavaScript 修改 HTML 之前就已经开始与你的界面进行交互。比如说,假定你想要在一张表单被提交到服务器之前用 JavaScript 来对其进行校验——该表单可能会在脚本加载之前就被提交了。如果你只是为了增强页面功能而编写脚本(而不是整个页面都依赖于该脚本),这个缺点倒也不是什么问题——只不过会比较恼人罢了。
具体哪种方法更适合你的网站,这完全由你决定;你甚至可以把两种方法混起来用——将功能非常重要的脚本放在 head 内,并将“可有可无”的脚本放在文档末尾。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"><html lang="en-en"> <head>?<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />?<title></title>?<script type="text/javascript" src="myimportantscripts.js"></script></head><body><!-- lots of HTML here --><script type="text/javascript">applyFunctionality();</script><script type="text/javascript" src="myscripts.js"></script></body></html>不管你将 JavaScript 放在何处,都应该确保你的脚本的放置顺序是正确的,因为浏览器会依次加载并解析。由于这个特性,我们在使用 JavaScript 的时候还得顾及另一个问题。
JavaScript 的安全性及其不足对于这一点,无论如何强调也不为过。JavaScript 是一门非常好的程序设计语言,可以帮助你建立反应迅速且漂亮的网站和应用程序,但它有一个非常严重的缺点,那就是安全性。简而言之,JavaScript 中没有安全模型,你绝不应当用 JavaScript 来对任何重要或机密的东西进行保护,加密,保障或存储。
页面上的每个脚本都有同样的权限——它们都可以互相访问,读取变量,访问函数,以及互相覆盖。如果页面中的第一个脚本内有个叫做 init() 的函数,最后一个脚本中也有一个同名的函数,那么第一个函数就会被覆盖。在本教程中的最佳实践一文中我们会再回来讨论这个问题。
如果你从头到尾都没有用过别人的脚本,上面这些倒也不是大问题。然而,由于大多数线上广告和统计跟踪都是用 JavaScript 来做的,情况就完全不一样了——你得一直使用第三方脚本。
脚本还可以用来读取 cookies,而且使用函数的 prototype 你还可以覆盖任何一个原生的 JavaScript 函数。最后,JavaScript 还可以轻易地被关掉,所以,你还是别再考虑把JavaScript 保护作为一种良好的安全措施了。
JavaScript 总是很容易被其它开发者所读取和分析。当然你也可以将你的脚本打包(移除所有不必要的空格)并加以混淆(使用随机变量和函数名),但即便是这些做法也可能被反向工程破解;因此这样做只能防止你自己使用你的代码。源代码的可获得性以及对源代码的阅读和分析能力可能是JavaScript得以流行的主要原因——长时间以来我们都靠偷看别人的代码来进行学习。幸运的是,现在这种状况已经结束了,我们现在有很好的书籍和教程。
尽管打包和混淆在安全措施方面没什么价值,但在将代码放到网上去之前,它们还是经常作为发布过程的一部分被应用在大中型脚本上。这样做有助于减少向用户提供网站服务所需的带宽。零零散散地这里省几个字节,那里省几个字节,可能对你关于小猫的博客没多大意义,但在对 google.com 之类的大型网站节约数量就相当可观了。
应该避免使用的技巧学习 JavaScript 最大的问题就是,现在有大量过时而且还可能不安全的信息。尤其令人沮丧的是这类信息的表述通常非常好,而且通过复制和粘贴某些现成的代码,可以给许多初学者造成一种“速成”的感觉。
由于 JavaScript 的应用环境是完全未知的(用户的设置可能是五花八门的),而且我们并不知道我们在网上所找到的代码到底是出于什么样的决定,才创建成这种特殊形式的,我们就不应该指责那些解决方案。然而,下面这些办法都是已经过时的了,你只应在需要支持那些老旧落后的浏览器的时候才使用这些方法。
document.write() — 你可以用 document.write()来将内容写进文档中,但这种做法存在若干问题:你这样做就是将HTML与脚本混合起来,并且你还得十分精确地在自己想要该内容出现的地方添加一个脚本节点,而这样会使你的页面变慢。对于方便地显示某段代码的结果(比如说在教学过程中或在测试/调试你的代码时)来说,这是一个很好的办法。但它不能作为一个向用户展示页面的方法,你不应将它应用在实际代码中。<noscript></noscript> — 就像其名字所指的那样,noscript 元素刚好与 script 元素相反。在该元素内的内容将显示给那些禁用了 JavaSrcipt 的用户看。使用 noscript 的主要原因是为了向那些浏览器中 JavaScript 不可用的用户提供替换内容。那些没有开启 JavaScript 的用户并不是成心想要为难你才那么做的——他们之所以这样做要么是出于安全的考虑,要么是因为他们所使用的浏览器不支持 JavaScript 。但可以放在 noscript 内来提供的内容是有限的,且你不应将其用来通知用户启用 JavaScript ——因为对某些用户来说这是不可能做到的。 <a href="javascript:doStuff)">…</a> — 这是一种非常常见的调用 JavaScript 功能的方法,大多数时候这种方法是用在不便使用按钮的情况下(在老式浏览器中你无法对按钮进行样式化)。问题在于这其实不是一个合法的链接,因为 javascript 并不是一个 internet 协议(比如 ftp:// 或 http://)。如果 JavaScript 被禁用,该链接也还是会被显示,并会给用户造成一种错误的期待,让他们觉得有点击后会随之发生什么事情。document.layers 和 document.all — 这两个是在老式浏览器中使用是 DOM 的解决方法(分别对应于 Netscape 4.x 和 IE4),而且如果你不需要支持这些浏览器(但如果你不得不这样做的话,我很同情...)的话,就完全不需要使用。总结初识 JavaScript 就到此结束了。本文没有对大量细节进行讲解,而是旨在为读者提供一个概述,告诉读者如何才能最好地将 JavaScript 应用到页面中去,以及该避免哪些问题。在下一篇教程中我们将通过一个真实的代码示例来讨论 JavaScript 编写最佳实践。