在人类漫漫的历史长河里,很难找到第二个由简单逻辑和抽象符号组合而成的,具有如此宏大信息量和丰富多彩内涵的领域。从某种意义上说,当你翻开这本书的时候,你已经踏入了一个任由你制定规则的未知世界。尽管你面对的仅仅是程序设计领域的冰山一角,但你将透过它,去领悟“道”的奥秘。在接下来的一段时间内,你会同我一起,掌握一种简单而优雅的神秘语言,学会如何将你的意志作用于它。这种语言中所蕴涵着的亘古之力,将为你开启通往神秘世界的大门……
1.1为什么选择JavaScript?
在一些人眼里,程序设计是一件神秘而浪漫的艺术工作,对他们来说,一旦选定某种编程语言,就会像一个忠贞的信徒一样坚持用它来完成任何事情,然而我不是浪漫的艺匠,大多数人也都不是,很多时候我们学习一种新技术的唯一目的,只是为了把手中的事情做得更好。所以,当你面对一项陌生的技术时,需要问的第一个问题往往是,我为什么选择它,它对我来说,真的如我所想的那么重要吗?
好,让我们带着问题开始。
1.1.1 用户的偏好:B/S模式
如果你坚持站在专业人员的角度,你就很难理解为什么B/S模式会那么受欢迎。如果你是一个资深的程序员,有时候你甚至会对那些B/S模式的东西有一点点反感。因为在你看来,浏览器、表单、DOM和其他一切与B/S沾边的东西,大多是行为古怪而难以驾驭的。以你的经验,你会发现实现同样的交互,用B/S来做通常会比用任何一种客户端程序来做要困难得多。
如果你尝试站在用户的角度,你会发现为什么大多数最终用户对B/S模式却是如此的青睐。至少你不必去下载和安装一个额外的程序到你的电脑上,不必为反复执行安装程序而困扰,不必整天被新的升级补丁打断工作,不必理会注册表、磁盘空间和一切对普通用户来说有点头疼的概念。如果你的工作地点不是固定的办公室,你日常工作的PC也不是固定的一台或者两台,那么,B/S的意义对你而言或许比想象的还要大。
大多数情况下,客户更偏好使用浏览器,而不是那些看起来比较专业的软件界面,专业人员则恰恰相反。
总之,用户的需求让B/S模式有了存在的理由,而迅速发展的互联网技术则加速了B/S应用的普及。随着一些优秀的Web应用产品出现,不但唤起了用户和业内人士对Ajax技术的关注,也令Web领域内的一个曾经被无数人忽视的脚本语言——JavaScript进入了有远见的开发人员和IT经理人的视线。于是在你的手边,也多了现在这本教程。
编写本书的时候,在TIOBE编程社区最新公布的数据中,JavaScript在世界程序开发语言中排名第十,这意味着JavaScript已经正式成为一种被广泛应用的热门语言。
1.1.2 在什么情况下用JavaScript
一路发展到今天,JavaScript的应用范围已经大大超出一般人的想象,但是,最初的JavaScript是作为嵌入浏览器的脚本语言而存在,而它所提供的那些用以表示Web浏览器窗口及其内容的对象简单实用,功能强大,使得Web应用增色不少,以至于直到今天,在大多数人眼里,JavaScript 表现最出色的领域依然是用户的浏览器,即我们所说的Web应用的客户端。客户端浏览器的JavaScript应用也正是本书讨论的重点内容。
作为一名专业程序员,当你在面对客户的时候,经常需要判断哪些交互需求是适合于JavaScript来实现的。而作为一名程序爱好者或者是网页设计师,你也需要了解哪些能够带给人惊喜的特效是能够由JavaScript来实现的。总之一句话,除了掌握JavaScript本身,我们需要学会的另一项重要技能是,在正确的时候、正确的地方使用JavaScript。对于JavaScript初学者来说学会判断正确使用的时机有时候甚至比学会语言本身更加困难。
作为项目经理,我经常接受来自客户的抱怨。因此我很清楚我们的JavaScript在带给客户好处的同时制造了太多的麻烦,相当多的灾难是由被错误使用的 JavaScript引起的。一些代码本不应该出现在那个位置,而另一些代码则根本就不应当出现。我曾经寻访过问题的根源,发现一个主要的原因由于 JavaScript的过于强大(在后面的小节中我们将会提到,另一个同样重要的原因是“脚本诱惑”),甚至超越了浏览器的制约范围,于是麻烦就不可避免的产生了,这就像你将一个魔鬼放入一个根本就不可能关住它的盒子里,那么你也就无法预料魔鬼会做出任何超出预期的举动。
毫无疑问,正确的做法是:不要放出魔鬼。所以,JavaScript程序员需要学会的第一个技巧就是掌握在什么情况下使用JavaScript才是安全的。
在什么情况下用JavaScript?给出一个简单的答案是:在任何不得不用的场合使用,除此以外,不要在任何场合使用!无懈可击的应用是不用,除非你确实无法找到一个更有效更安全的替代方案。也许这个答案会让读到这里的读者有些郁闷,但是,我要很严肃地提醒各位,由于JavaScript比大多数人想象的要复杂和强大得多,所以它也比大多数人想象得要危险得多。在我的朋友圈子里,许多资深的JavaScript程序员(包括我在内)偶尔也不得不为自己一时疏忽而做出的错误决定让整个项目团队在“脚本泥潭”中挣扎好一阵子。所以这个建议从某种意义上说也是专家们的血泪教训。最后向大家陈述一个令人欣慰的事实,即使是像前面所说的这样,在Web应用领域,JavaScript的应用范围也仍然是相当广泛的。
Ø 在本节的最后三个小节里,我们将进一步展开讨论关于JavaScript使用的话题。
1.1.3 对JavaScript的一些误解
JavaScript是一个相当容易误解和混淆的主题,因此在对它进一步研究之前,有必要澄清一些长期存在的有关该语言的误解。
1.1.3.1 JavaScript和Java
这是最容易引起误会的一个地方,这个Java-前缀似乎暗示了JavaScript和Java的关系,也就是JavaScript是Java的一个子集。看上去这个名称就故意制造混乱,然后随之而来的是误解。事实上,这两种语言是完全不相干的。
JavaScript和Java的语法很相似,就像Java和C的语法相似一样。但它不是Java的子集就像Java也不是C的子集一样。在应用上,Java要远比原先设想的好得多(Java原称Oak)。
JavaScript 的创造者是Brendan Eich,最早的版本在NetScape 2中实现。在编写本书时,Brendan Eich在Mozilla公司任职,他本人也是JavaScript的主要革新者。而更加有名的Java语言,则是出自Sun Microsystems公司的杰作。
JavaScript最初叫做LiveScript,这个名字本来并不是那样容易混淆,只是到最后才被改名为JavaScript,据说起同Java相似的名字纯粹是一种行销策略。
尽管JavaScript和Java完全不相干,但是事实上从某种程度上说它们是很好的搭档。JavaScript可以控制浏览器的行为和内容,但是却不能绘图和执行连接(这一点事实上并不是绝对的,通过模拟是可以做到的)。而Java虽然不能在总体上控制浏览器,但是却可以绘图、执行连接和多线程。客户端的JavaScript可以和嵌入网页的Java applet 进行交互,并且能够对它执行控制,从这一意义上来说,JavaScript真的可以脚本化Java。
1.1.3.2披着C外衣的Lisp
JavaScript的C风格的语法,包括大括号和复杂的for 语句,让它看起来好像是一个普通的过程式语言。这是一个误导,因为JavaScript和函数式语言如Lisp和Scheme有更多的共同之处。它用数组代替了列表,用对象代替了属性列表。函数是第一型的。而且有闭包。你不需要平衡那些括号就可以用λ算子。
Ø 关于JavaScript闭包和函数式的内容,在本书的第23章中会有更详细的介绍。
1.1.3.3思维定势
JavaScript 是原被设计在Netscape Navigator 中运行的。它的成功让它成为几乎所有浏览器的标准配置。这导致了思维定势。认为JavaScript是依赖于浏览器的脚本语言。其实,这也是一个误解。 JavaScript也适合很多和Web无关的应用程序。
早些年在学校的时候,我和我的实验室搭档曾经研究过将JavaScript作为一种PDA控制芯片的动态脚本语言的可行性,而在我们查阅资料的过程中发现一些对基于嵌入式环境的动态脚本语言实现的尝试,我们有理由相信,JavaScript在某些特定的嵌入式应用领域中也能够表现得相当出色。
1.1.3.4业余爱好者
一个很糟糕的认知是:JavaScript过于简朴,以至于大部分写JavaScript的人都不是专业程序员。他们缺乏写好程序的修养。JavaScript有如此丰富的表达能力,他们可以任意用它来写代码,以任何形式。
事实上,上面这个认知是曾经的现实,不断提升的Web应用要求和Ajax彻底改变了这个现实。通过学习本书,你也会发现,掌握JavaScript依然需要相当高的专业程序员技巧,而不是一件非常简单的事情。不过这个曾经的现实却给JavaScript带来了一个坏名声──它是专门为外行设计的,不适合专业的程序员。这显然是另一个误解。
推广JavaScript最大的困难就在于消除专业程序员对它的偏见,在我的项目团队中许多有经验的J2EE程序员却对JavaScript停留在一知半解甚至茫然的境地,他/她们不愿意去学习和掌握JavaScript,认为这门脚本语言是和浏览器打交道的美工们该干的活儿,不是正经程序员需要掌握的技能。这对于Web应用开发来说,无疑是一个相当不利的因素。
1.1.3.5面向对象
JavaScript 是不是面向对象的?它拥有对象,可以包含数据和处理数据的方法。对象可以包含其它对象。它没有类(在JavaScript 2.0真正实现之前),但它却有构造器可以做类能做的事,包括扮演类变量和方法的容器的角色。它没有基于类的继承,但它有基于原型的继承。两个建立对象系统的方法是通过继承和通过聚合。JavaScript两个都有,但它的动态性质让它可以在聚合上超越。
一些批评说JavaScript不是真正面向对象的因为它不能提供信息的隐藏。也就是,对象不能有私有变量和私有方法:所有的成员都是公共的。但随后有人证明了JavaScript对象可以拥有私有变量和私有方法。另外还有批评说JavaScript不能提供继承,但随后有人证明了JavaScript不仅能支持传统的继承还能应用其它的代码复用模式。
说 JavaScript是一种基于对象的语言,是一种正确而略显保守的判断,而说JavaScript不面向对象,在我看来则是错误的认知。事实上有充足的理由证明JavaScript是一种的面向对象的语言,只是与传统的class-based OO(基于类的面向对象)相比,JavaScript有它与众不同的地方,这种独特性我们称它为prototype-based OO(基于原型的面向对象)。
Ø 关于JavaScript面向对象的内容,在本书的第21章中会有更详细的介绍。
1.1.3.6其他误解
除了以上提到的几点之外,JavaScript还有许多容易令人迷惑和误解的特性,这些特性使得JavaScript成为世界上最被误解的编程语言。
Ø 如果读者对这方面有兴趣,可以详细阅读下面这篇文章
http://javascript.crockford.com/javascript.html [Douglas Crockford]
1.1.4 警惕!脚本诱惑
前面我们提到过,许多专业程序员拒绝去了解如何正确使用JavaScript,另一些则是缺乏对JavaScript足够的认知和应用经验。但是在B/S 应用中,相当多的情况下,要求开发人员不得不采用JavaScript。于是,一个问题产生了,大量的JavaScript代码拷贝出现在页面的这个或者那个地方,其中的大部分是不必要的,另一部分可能有缺陷。我们的开人员没有办法(也没有意识到)去判断这些代码是否必要,以及使用它们会带来哪些问题。
如果你的B/S应用中的JavaScript不是由专业的JavaScript程序员来维护的,那么当你对你的开发团队进行一次小小的代码走查时,你甚至可能会发现90%的JavaScript代码被错误地使用,这些错误使用的代码浪费了用户大量的网络带宽、内存和CPU资源,提升了对客户端配置的要求,降低了系统的稳定性,甚至导致许多本来可以避免的安全问题。
由于浏览器的JavaScript可以方便地被复制粘贴,因此,一个特效或者交互方式往往在真正评估它的必要性之前便被采用——客户想要它,有人使用过它,程序员复制它,而它就出现在那儿,表面上看起来很完美,于是,所谓的脚本诱惑就产生了。
事实上,在我们真正使用JavaScript之前,需要反复问自己一个重要问题是,究竟是因为有人想要它,还是因为真正有人需要它。在你驾驭 JavaScript马车之前,你必须学会抵制脚本诱惑,把你的脚本用在必要的地方,永远保持你的Web界面简洁,风格一致。
在用户眼里,简洁一致的风格与提供强大而不常用的功能和看起来很COOL而实际上没有什么功用的界面特效相比起来,前者更能令他们觉得专业。毕竟,大部分用户和你我一样,掌握一个陌生的环境和新的技能只是为了能够将事情做得更快更好。除非你要提供的是一个类似于Qzone之类的娱乐程序,你永远也不要大量地使用不必要的JavaScript。
1.1.5 隐藏在简单表象下的复杂度
专业人员不重视JavaScript的一个重要原因是,他们觉得JavaScript是如此的简单,以至于不愿意花精力去学习(或者认为不用学习就能掌握)。前面提到过的,这实际上是一种误解。事实上,在脚本语言中,JavaScript属于相当复杂的一门语言,它的复杂程度未必逊色于Perl和 Python。
另一个业内的偏见是脚本语言都是比较简单的,实际上,一门语言是否脚本语言往往是它的设计目标决定的,简单与复杂并不是区分脚本语言和非脚本语言的标准。JavaScript即使放到非脚本语言中来衡量,也是一门相当复杂的语言。
之所以很多人觉得JavaScript过于简单,是因为他们大量使用的是一些JavaScript中看似简单的文法,解决的是一些看似简单的问题,真正复杂而又适合JavaScript的领域却很少有人选择JavaScript,真正强大的用法很少被涉及。JavaScript复杂的本质被一个个简单应用的表象所隐藏。
我曾经给一些坚持认为JavaScript过于简单的开发人员写过一段小代码,结果令他们中的大部分内行人大惊失色,那段代码看起来大致像下面这个样子:
var a = [-1,-1,1,-3,-3,-3,2,2,-2,-2,3,-1,-1];
function f(s, e)
{
var ret = [];
for(var i in s){
ret.push(e(s[i]));
}
return ret;
}
var b = f(a, function(n){return n>0?n:0});
alert(b);
这是本书中出现的第一段JavaScript代码,也许现在你看来,它有那么一点点令人迷惑,但是不要紧,在本书后面的章节中,你会慢慢理解这段代码的含义以及它的无穷妙味。而现在你完全可以跳过它的实际内容,只要需要知道这是一段外表看起来简单的魔法代码就够了。
因为这段代码而尖叫的不仅仅包括我的这些程序员朋友,事实上,更兴奋的是另一些电子领域的朋友,他们写信给我反馈说,在此之前他们从来没有见到过如此形式简洁而优雅的数字高通滤波器,更令人欣喜的是,它的阈值甚至是可调节的:
var b = f(a, function(n){return n>=-1?n:0});
如果你想要,它也很容易支持低通滤波:
var b = f(a, function(n){return n<0?n:0});
用一个小小的堆栈或者其他伎俩,你也可以构造出一族差分或者其他更为复杂的数字设备,而它们明显形式相近并且结构优雅。
总之,不要被简单的表象所迷惑,JavaScript的复杂度往往很大程度上取决于你的设计思路和你的使用技巧。JavaScript的确是一门可以被复杂使用的程序设计语言。
1.1.6 令人迷惑的选择:锦上添花还是雪中送炭
本节最后的这个话题在前面已经被隐讳地提到过多次,实际上,本小节围绕的话题依然是什么时候使用JavaScript。一种比较极端的观点是在必须的时候采用,也就是前面所说的不得不用的场合,另一种比较温和一点的观点则坚持在需要的时候使用,这种观点认为当我们可以依靠JavaScript令事情变得更好的时候,我们就采用它。
事实上,就我个人而言,比较支持“必须论”,这是因为从我以往的经验来看,JavaScript是难以驾驭的,太多的问题由使用JavaScript不当而产生,其中的一部分相当令人困扰,彻底解决它们的办法就是尽可能降低JavaScript的使用频率,也尽可能将它用在真正适合它的地方。当然万事没有绝对,在何时使用 JavaScript永远是一个难题,然而不管怎么说同“锦上添花”相比,JavaScript程序员也许应当更多考虑的是如何“雪中送炭”。
1.1.7回到问题上来
本节要解决的问题是为什么选择JavaScript,然而在相当多的篇幅里,我们都在试图寻找一些少用和不用JavaScript的理由,尽管如此,抛开大部分不适合JavaScript的位置和时机,浏览器上依然会经常地见到JavaScript的身影,对于浏览器来说,JavaScript实在是一个不可缺少的修饰。
你再也找不到任何一种优雅简朴的脚本语言如此适合于在浏览器中生存。在本书的第2章,我们将具体接触嵌入浏览器中的JavaScript。
最后,用一句话小结本节的内容——我们之所以选择JavaScript,是因为:Web应用需要JavaScript,我们的浏览器、我们的程序员和我们的用户离不开它。
No comments:
Post a Comment