前言
从2006年第一次接触JavaScript至今,算来也有四年时间了。上大学的时候,有一段时间沉迷于函数式编程,而那时候对JavaScript的理解仅仅局限在这是用来做网页的一种脚本,那些很恶心的弹出窗口和不断在页面上漂浮的黄色广告就是用JavaScript做出来的。工作之后,由于我们产品本身就是基于WEB展现的,而这个时候Ajax已经复兴数年了,但是于我,则只有“Ajax可以实现页面的局部刷新”这样一个概念。在实际的应用中,我才有机会面对真正的JavaScript,早期关于函数式编程的概念开始在我的记忆力复苏,而真正将JavaScript比较熟练的应用在产品的开发中,那已经是09年年末了。
开始研究JavaScript,是从2008年的5月左右,我从当当上买了一本犀牛书,并下载到一本蝴蝶书,结合着实际工作的的要求,一步一步的开始了JavaScript的探索。刚开始也只是被陷入在DOM的泥潭中,慢慢的开始考虑更进一步的东西,比如JSON作为数据交换,window对象的一些特殊的方法如eval等等,事实上仍然是陷入在语法的细节中。当终于有一天,理解了变量的作用域,理解了闭包,理解了函数的一等性,以往用来类比的来源于其他语言的所有概念则完全被颠覆了,当理解了JavaScript中的这些基本概念(虽然难以理解,但是它们的确是基本概念)之后,在回顾来时的路,则有些一览众山小的意思。
但是,这些看似基本的概念,在初学时如果混入了其他语言的概念以进行类比,则后患无穷,所以,学习JavaScript其实就一句话:“将JavaScript当成一门新的语言来学习”。鉴于我学习JavaScript的历程中,遇到了很多问题,但是最终都一一克服了,在这个过程中,有些心得,有些体会,就分节贴出来,做成一个系列,以方便初学JavaScript的朋友们。
第一章 概述
1.1 Javascript简史
在20世纪90年代,也就是早期的WEB站点上,所有的网页内容都是静态的,所谓静态是指,除了点击超链接,你无法通过任何方式同页面进行交互,比如让页面元素接受事件,修改字体等。人们于是迫切的需要一种方式来打破这个局限,于是到了1996年,网景(Netscape)公司开始研发一种新的语言Mocha,并将其嵌入到自己的浏览器Netscape中,这种语言可以通过操纵DOM(Document Object Model,文档对象模型)来修改页面,并加入了对鼠标事件的支持。Mocha使用了C的语法,但是设计思想上主要从函数式语言Scheme那里取得了灵感。当Netscape 2发布的时候,Mocha被改名为LiveScript,当时可能是想让LiveScript为WEB页面注入更多的活力。后来,考虑到这个脚本语言的推广,网景采取了一种宣传策略,将LiveScript更名为JavaScript,目的是为了跟当时非常流行的面向对象语言Java发生暧昧的关系。这种策略显然颇具成效,以至于到现在很多初学者还会为JavaScript和Java的关系而感到困惑。
Javascript取得成功了之后,确实为页面注入了活力,微软也紧接着开发自己的浏览器脚本语言,一个是基于BASIC语言的VBScript,另一个是跟Javascript非常类似的Jscript,但是由于Javascript已经深入人心,所以在随后的版本中,微软的IE几乎是将Javascript作为一个标准来实现。当然,两者仍然有不兼容的地方。1996年后期,网景向欧洲电脑厂商协会(ECMA)提交了Javascript的设计,以申请标准化,ECMA去掉了其中的一些实现,并提出了ECMAScript-262标准,并确定Javascript的正式名字为ECMAScript,但是JavaScript的名字已经深入人心,故本书中仍沿用Javascript这个名字。
1.1.1动态网页
WEB页面在刚开始的时候,是不能动态修改其内容的,要改变一个页面的内容,需要先对网站上的静态HTML文件进行修改,然后需要刷新浏览器。后来出现的JSP,ASP等服务器端语言可以为页面提供动态的内容,但是如果没有JavaScript则无法在服务器返回之后动态的在前端修改页面,也无法有诸如鼠标移上某页面元素则高亮该元素之类的效果,因此JavaScript的出现大大的丰富了页面的表现,提高了用户体验。
而当AJAX流行起来之后,更多的非常绚丽的WEB应用涌现了,而且呈越来越多的趋势,如Gmail,Google Map,Google Reader,Remember the milk,facebook等等优秀的WEB2.0应用,都大量的使用了JavaScript及其衍生的技术AJAX。
1.1.2浏览器之战
1.1.3标准
1.2 JavaScript语言特性
JavaScript是一门动态的,弱类型,基于原型的脚本语言。在JavaScript中“一切皆对象”,在这一方面,它比其他的OO语言来的更为彻底,即使作为代码本身载体的function,也是对象,数据与代码的界限在JavaScript中已经相当模糊。虽然它被广泛的应用在WEB客户端,但是其应用范围远远未局限于此。下面就这几个特点分别介绍:
1.2.1动态性
动态性是指,在一个Javascript对象中,要为一个属性赋值,我们不必事先创建一个字段,只需要在使用的时候做赋值操作即可,如下例:
//定义一个对象 var obj = new Object(); //动态创建属性name obj.name = "an object"; //动态创建属性sayHi obj.sayHi = function(){ return "Hi"; } obj.sayHi();
加入我们使用Java语言,代码可能会是这样:
class Obj{ String name; Function sayHi; public Obj(Sting name, Function sayHi){ this.name = name; this.sayHi = sayHi; } } Obj obj = new Obj("an object", new Function());
动态性是非常有用的,这个我们在第三章会详细讲解。
1.2.2弱类型
与Java,C/C++不同,Javascript是弱类型的,它的数据类型无需在声明时指定,解释器会根据上下文对变量进行实例化,比如:
//定义一个变量s,并赋值为字符串 var s = "text"; print(s); //赋值s为整型 s = 12+5; print(s); //赋值s为浮点型 s = 6.3; print(s); //赋值s为一个对象 s = new Object(); s.name = "object"; print(s.name);
结果为:
17
6.3
Object
可见,Javascript的变量更像是一个容器,类似与Java语言中的顶层对象Object,它可以是任何类型,解释器会根据上下文自动对其造型。
弱类型的好处在于,一个变量可以很大程度的进行复用,比如String类型的name字段,在被使用后,可以赋值为另一个Number型的对象,而无需重新创建一个新的变量。不过,弱类型也有其不利的一面,比如在开发面向对象的Javascript的时候,没有类型的判断将会是比较麻烦的问题,不过我们可以通过别的途径来解决此问题。
1.2.3解释与编译
通常来说,Javascript是一门解释型的语言,特别是在浏览器中的Javascript,所有的主流浏览器都将Javascript作为一个解释型的脚本来进行解析,然而,这并非定则,在Java版的Javascript解释器rhino中,脚本是可以被编译为Java字节码的。
解释型的语言有一定的好处,即可以随时修改代码,无需编译,刷新页面即可重新解释,可以实时看到程序的结果,但是由于每一次都需要解释,程序的开销较大;而编译型的语言则仅需要编译一次,每次都运行编译过的代码即可,但是又丧失了动态性。
我们将在第九章和第十章对两种方式进行更深入的讨论。
1.3 Javascript应用范围
当Javascript第一次出现的时候,是为了给页面带来更多的动态,使得用户可以与页面进行交互为目的的,虽然Javascript在WEB客户端取得了很大的成功,但是ECMA标准并没有局限其应用范围。事实上,现在的Javascript大多运行与客户端,但是仍有部分运行于服务器端,如Servlet,ASP等,当然,Javascript作为一个独立的语言,同样可以运行在其他的应用程序中,比如Java版的JavaScript引擎Rhino,C语言版的SpiderMonkey等,使用这些引擎,可以将JavaScript应用在任何应用之中。
1.3.1客户端Javascript
客户端的JavaScript随着AJAX技术的复兴,越来越凸显了Javascript的特点,也有越来越多的开发人员开始进行JavaScript的学习,使用Javascript,你可以使你的WEB页面更加生动,通过AJAX,无刷新的更新页面内容,可以大大的提高用户体验,随着大量的JavaScript包如jQuery, ExtJS,Mootools等的涌现,越来越多的绚丽,高体验的WEB应用被开发出来,这些都离不来幕后的JavaScript的支持。
图JavaScript实现的一个WEB幻灯片
浏览器中的JavaScript引擎也进行了长足的发展,比如FireFox 3,当时一个宣传的重点就是速度比IE要快,这个速度一方面体现在页面渲染上,另一方面则体现在JavaScript引擎上,而Google的Chrome的JavaScript引擎V8更是将速度发展到了极致。很难想象,如果没有JavaScript,如今的大量的网站和WEB应用会成为什么样子。
我们可以看几个例子,来说明客户端的JavaScript的应用程度:
图 ExtJS实现的一个网络相册,ExtJS是一个非常优秀的JavaScriipt库
图 ExtJS实现的一个表格,具有排序,编辑等功能
当然,客户端的JavaScript各有侧重,jQuery以功能见长,通过选择器,可以完成80%的页面开发工作,并且提供强大的插件机制,下图为jQuery的UI插件:
总之,随着Ajax的复兴,客户端的JavaScript得到了很大的发展,网络上流行着大量的优秀的JavaScript库,现在有一个感性的认识即可,我们在后边的章节会择其尤要者进行详细讲解。
1.3.2服务端Javascript
相对客户端而言,服务器端的JavaScript相对平淡很多,但是随着JavaScript被更多人重视,JavaScript在服务器端也开始迅速的发展起来,Helma, Apache Sling等等。在服务器端的JavaScript比客户端少了许多限制,如本地文件的访问,网络,数据库等。
一个比较有意思的服务端JavaScript的例子是Aptana的Jaxer,Jaxer是一个服务器端的Ajax框架,我们可以看这样一个例子(例子来源于jQuery的设计与实现这John Resig):
<html> <head> <script src="http://code.jquery.com/jquery.js" runat="both"></script> <script> jQuery(function($){ $("form").submit(function(){ save( $("textarea").val() ); return false; }); }); </script> <script runat="server"> function save( text ){ Jaxer.File.write("tmp.txt", text); } save.proxy = true; function load(){ $("textarea").val( Jaxer.File.exists("tmp.txt") ? Jaxer.File.read("tmp.txt") : ""); } </script> </head> <body onserverload="load()"> <form action="" method="post"> <textarea></textarea> <input type="submit"/> </form> </body> </html>
runat属性说明脚本运行在客户端还是服务器端,client表示运行在客户端,server表示运行在服务器端,而both表示可以运行在客户端和服务器端,这个脚本可以访问文件,并将文件加载到一个textarea的DOM元素中,还可以将textarea的内容通过Form表单提交给服务器并保存。
再来看另一个例子,通过Jaxer对数据库进行访问:
<script runat="server"> var rs = Jaxer.DB.execute("SELECT * FROM table"); var field = rs.rows[0].field; </script>
通过动态,灵活的语法,再加上对原生的资源(如数据库,文件,网络等)操作的支持,服务器端的JavaScript应用将会越来越广泛。
当Google的JavaScript引擎V8出现以后,有很多基于V8引擎的应用也出现了,其中最著名,最有前景的当算Node.js了,下面我们来看一下Node.js的例子:
var sys = require('sys'),
http = require('http');
http.createServer(function (req, res) {
setTimeout(function () {
res.sendHeader(200, {'Content-Type': 'text/plain'});
res.sendBody('Hello World');
res.finish();
}, 2000);
}).listen(8000);
sys.puts('Server running at http://127.0.0.1:8000/');
保存这个脚本为sayHello.js,然后运行:
node sayHello.js
程序将会在控制台上打印:
Server running at http://127.0.0.1:8000/
访问http://127.0.0.1:8000,两秒钟之后页面会响应:Hello, World。
再来看另一个官方提供的例子:
var tcp = require('tcp');
var server = tcp.createServer(function (socket) {
socket.setEncoding("utf8");
socket.addListener("connect", function () {
socket.send("hello\r\n");
});
socket.addListener("receive", function (data) {
socket.send(data);
});
socket.addListener("eof", function () {
socket.send("goodbye\r\n");
socket.close();
});
});
server.listen(7000, "localhost");
访问localhost的7000端口,将建立一个TCP连接,编码方式为utf-8,当客户端连接到来时,程序在控制台上打印
hello
当接收到新的数据时,会将接收到的数据原样返回给客户端,如果客户端断开连接,则向控制台打印:
goodbay
Node提供了丰富的API来简化服务器端的网络编程,由于Node是基于一个JavaScript引擎的,因此天生的就具有动态性和可扩展性,因此在开发网络程序上,确实是一个不错的选择。
1.3.3其他应用中的Javascript
通过使用JavaScript的引擎的独立实现,比如Rhino,SpliderMonkey,V8等,可以将JavaScript应用到几乎所有的领域,比如应用程序的插件机制,高级的配置文件分析,用户可定制功能的应用,以及一些类似与浏览器场景的比如Mozilla的ThunderBrid,Mozilla的UI框架XUL,笔者开发的一个Todo管理器sTodo(在第十章详细讨论)等。
图 sTodo 一个使用JavaScript来提供插件机制的Java桌面应用
Java版的JavaScript引擎原生的可以通过使用Java对象,那样将会大大提高JavaScript的应用范围,如数据库操作,服务器内部数据处理等。当然,JavaScript这种动态语言,在UI方面的应用最为广泛。
著名的Adobe reader也支持JavaScript扩展,并提供JavaScript的API来访问PDF文档内容,可以通过JavaScript来定制Adobe Reader的界面以及功能等。
app.addMenuItem({ cName: "-", // menu divider cParent: "View", // append to the View menu cExec: "void(0);" }); app.addMenuItem({ cName: "Bookmark This Page &5", cParent: "View", cExec: "AddBookmark();", cEnable: "event.rc= (event.target != null);" }); app.addMenuItem({ cName: "Go To Bookmark &6", cParent: "View", cExec: "ShowBookmarks();", cEnable: "event.rc= (event.target != null);" }); app.addMenuItem({ cName: "Remove a Bookmark", cParent: "View", cExec: "DropBookmark();", cEnable: "event.rc= (event.target != null);" }); app.addMenuItem({ cName: "Clear Bookmarks", cParent: "View", cExec: "ClearBookmarks();", cEnable: "event.rc= true;" });
为Adobe Reader 添加了4个菜单项,如图:
另一个比较有意思的JavaScript实例为一个在线的遗传算法的演示,给定一个图片,然后将一些多边形(各种颜色)拼成一个图片,拼图的规则为使用遗传算法,使得这些多变形组成的图片与目标图片最为相似:
可见,JavaScript在其他方面的也得到了广泛的应用。
附:由于作者本身水平有限,文中难免有纰漏错误等,或者语言本身有不妥当之处,欢迎及时指正,提出建议,参与讨论,谢谢大家!
19 楼 o0snow 2011-11-24 16:55
厉害
18 楼 deerfen 2011-04-17 16:16
17 楼 xiaohui886688 2010-11-17 10:50
16 楼 wu_007 2010-10-22 10:26
15 楼 kongxiantao 2010-09-30 11:17
14 楼 jdgnewtouch 2010-09-17 11:32
13 楼 david_xu 2010-09-01 17:02
12 楼 abruzzi 2010-08-26 21:18
node sayHello.js
执行不出来啊,是在dos下执行吗,是需要下载node.js才能运行吗 3x
跟node沒有关系,node是一个js库http://nodejs.org/api.html,自己写的sayHello.js有很多种方法运行,最简单的是嵌入到网页上,如果只是学习JavaScript本身,完全可以使用别的脚本引擎,如rhino, spidermonkey,v8等均可。
11 楼 hnzhoujunmei 2010-08-26 16:52
node sayHello.js
执行不出来啊,是在dos下执行吗,是需要下载node.js才能运行吗 3x
10 楼 honglin1983 2010-08-17 19:50
9 楼 zhameng 2010-07-09 15:13
8 楼 lgmuliandie 2010-07-09 14:36
7 楼 ordinance 2010-06-27 18:02
6 楼 abruzzi 2010-04-28 13:35
我会注明出处的。
我这边没有问题,可以转载,注明出处就可以了。不过建议你仔细看看JavaEye的版规,小心被扣分,呵呵。
5 楼 pouyang 2010-04-28 12:53
4 楼 pouyang 2010-04-28 12:52
我会注明出处的。
3 楼 abruzzi 2010-04-27 16:59
大师可不敢当,希望大家可以从这个系列中获益,呵呵。
2 楼 xiaochuntu 2010-04-27 16:13
1 楼 zhicheng19830219 2010-04-19 22:19