Java 开发 2.0: 面向 Java 开发人员的 JavaScript

Java 开发人员关于 JavaScript 变量、类型、函数等的初级读本

Java™ 开发人员一直不看好 JavaScript,因为用它来编程显得太过轻量级了,而作为脚本又显得太过笨重。但有人还在使用 JavaScript,因为它是 GWT 与 Node.js 之类优秀 Web 技术的基础。在本期 Java 开发 2.0 中,Andrew Glover 解释了为何 JavaScript 是现代 Java 开发人员的重要工具。然后介绍了构建当前 Web 的一流应用程序所需的语法,包括 JavaScript 变量、类型、函数、和类。

Andrew Glover, 作家和开发人员, Beacon50

Andrew GloverAndrew Glover 是具有行为驱动开发、持续集成和敏捷软件开发激情的开发人员、作家、演说家和企业家。他是 easyb 行为驱动开发(Behavior-Driven Development,BDD)框架的创建者和三本书的合著者:持续集成Groovy 在行动Java 测试模式。您可以通过他的博客与他保持一致并在 Twitter(http://twitter.com/aglover)上关注他。



2011 年 8 月 10 日

对于早期的 Java 平台,新闻记者,甚至新手程序员经常会将 JavaScript 与 Java 语言搞混。这两种语言之所以普及,是因为它们都适合于 Web 编程,而且它们也经常同时出现在大众面前。今天,大多数人都能区分这两种语言,但 Java 开发人员仍然普遍不看好 JavaScript,甚至觉得它不适用于脚本中。但现实情况是,JavaScript(很像 Java 语言)不但存在,甚至还在不断演进。它是 Ajax 这类客户端编程技术与 Node.js 这类服务器端编程技术的基础,它对于移动应用程序开发的出现也很重要。它也支持在非常流行的 Google Web Toolkit(或 GWT)中编译 Java 代码。

在本期 Java development 2.0 中,我将解释为何 JavaScript 对于当前的 Java 开发人员很重要,还会简要介绍一些非常有用的 JavaScript 语法,说明它与 Java 语言的区别,还会把它与 Groovy 和 Ruby 之类现代动态语言进行对比。

关于本系列

自 Java 技术诞生以来,Java 开发的前景已经发生了根本性的变化。这得益于成熟的开源框架和可靠的 for-rent 部署基础设施,现在可以快速而廉价地组装、测试、运行、和维护 Java 应用程序。在本 系列 中,Andrew Glover 探讨了使得这一新的 Java 开发范例成为可能的技术与工具。

当时和现在:为何 JavaScript 很重要

Netscape 于 1995 年引入了 JavaScript,它很快就流行起来了。最主要的原因是 Web 作为商业媒体平台的出现:使用 JavaScript,您(依然)可以通过编程来影响浏览器中 Web 页面的特性。那这是个很棒的工具!HTML 表单验证与受限图片欺骗(limited image trickery)是主题。

自那时起 JavaScript 就具有多个化身。Netscape 曾一度拥有一个产品,Netscape Application Server,它正是基于服务器端 JavaScript 来构建的 Web 应用程序。多年以后,由于 Ajax 和 Prototype、JQuery、和 Extjs 之类部件库的引入,重新引起了人们对 JavaScript 的兴趣。最近,服务器端 JavaScript 被用于 Node.js 当中,这是利用 Google's V8 JavaScript 引擎构建服务器端 Web 应用程序的基于事件的 I/O 框架。

Netscape 做了一件很有前瞻性的事,就是把 JavaScript 提交到 Ecma International 来进行标准化。这就是人们称 JavaScript 为 ECMAScript 的原因。更重要的是,这也是众多 Web 浏览器支持 ECMAScript 的原因。因此,Web 应用程序大都会采用 JavaScript,这一点没有改变过。目前还没有能与之相比的其他浏览器兼容脚本语言。

Node.js

Node.js(见 参考资料Resources)是服务器端、高并发、基于事件的框架。在处理大量有关并发编程的问题时,Node.js 程序比具有线程的程序效率更高。Node.js 相对比较新,围绕该技术的创新令人期待。了解 JavaScript 是使用 Node.js 相关工具的关键。

当前,尽管 JavaScript 的名声不好,它仍然是应用最广(最有用)的语言之一。如果您是位 Java 程序员(或者 Ruby、Python、或 PHP 程序员),那么您可能曾用过 JavaScript ,或者在不久的将来会使用 JavaScript。了解 JavaScript 的一些特性,有助于构建优秀的 Web 应用程序。此外,这有助于使用 Node.js,甚至还能增强您对 GWT 内部技术的了解。

在下一小节中,我将关注 JavaScript 语法的主要元素,重点介绍一些细节内容,这将有助于 Java 开发人员的提高。然而,我首先想打破一个关于 JavaScript 的神话:就是您需要一个 Web 页面来与其交互。


在 Chrome 中使用 JavaScript

在过去,JavaScript 需要浏览器,并间接地需要一个 Web 页面来执行。这对于一些开发人员来说是个麻烦,甚至是个障碍。幸运的是浏览器已经发展了;今天不论 Firefox 还是 Chrome 都提供了用于执行 JavaScript 的 IDE。

我喜欢 Chrome 漂亮的 JavaScript 控制台。就像 Ruby's IRB 或者 Python's shell,Chrome 提供不需要 Web 页面的用于浏览 JavaScript 的交互式环境。

CoffeeScript

如果您喜欢 JavaScript 的功能,但不喜欢它的语法,那么您可以尝试一下 CoffeeScript。CoffeeScript 是 “编译成 JavaScript 的小型语言” — 也就是说,CoffeeScript 通过简化 JavaScript 的一些语法,使 JavaScript 编程更加方便。CoffeeScript 更像 Ruby 或者 Python,但能提供 JavaScript 的效果。见 参考资料 中 CoffeeScript 的相关内容。

想要了解 Chrome's JavaScript 控制台,需要 下载用于您 OS 中的 Chrome。然后,打开一个新的空白标签(也就是说,不要指向 Web 页面)并选择 View > Developer > JavaScript Console。在 Chrome 窗口的底部,会弹出 JavaScript 开发人员控制台。可通过选择控制台左下角的 Undock 图标来使其成为独立对话框。然后可选择右上角的 Console 图标,来打开用于和 JavaScript 交互的空白窗口,如图 1 所示:

图 1. 在 Google Chrome 中与 JavaScript 交互
截屏展示了 Google Chrome's JavaScript 控制台

现在来看一些语法。


JavaScript 变量

JavaScript 是一个比较容易使用的语言,它能容忍很多编程错误,并仍然能在加载的 Web 页中执行。JavaScript 元素经常没有任何提示就失败了,这大部分都是好消息。如果 JavaScript 语言草率地禁止页面加载,那么早期的 Web 将是一片混乱。也就是说,当我们利用 JavaScript 来做我们喜欢做的事时(比如异步更新页面状态),草率使用 JavaScript 将付出代价。由于这个原因,Java 开发人员应该花时间真正了解 JavaScript 语法的特定方面。

JavaScript 变量的处理对理解来说很重要。例如,您想定义一个变量 foo,可以直接定义或者通过 var 声明,如清单 1 所示:

清单 1. 变量 foo
foo = 'foo'
var bar = 'bar'

清单 1 中的 foo 是 JavaScript 中的有效变量。但它缺少 var 声明,这是个全局变量。因此利用 var 定义的变量是有范围的(例如,在定义它的函数中)。

通常,全局变量比较麻烦。它们很容易造成变量使用的混乱,因为全局变量可在 JavaScript 应用程序中的任何地方进行访问和改变,这将导致潜在 bug。因此,当在 JavaScript 中编程时,不要忘了对变量应用 var


基元和对象

尽管 JavaScript 不够完善,但在类型方面十分简单。事实上,JavaScript 仅有 4 个基本类型,其中三个是基元。JavaScript 的基元类型是 NumberString、和 Boolean。您可通过 JavaScript typeof 运算符来在操作中查看这些类型。

我们来一起看一下该问题。在 Chrome's JavaScript 中,输入清单 2 中的内容:

清单 2. Activating types
var string = "test"
typeof string

可以看到控制台输出值 “string”。还要注意在 JavaScript 中分号是可选的。正如在流行的语言当中一样,string 通过引号来划定;因此,数字通过数字来划定。Booleans 通过值 true 或者 false 来划定,没有分号。

清单 3. JavaScript truth 与 numbers
var aNumber = 10
var anotherNumber = 0.99
var aBool = true
var notABoolean = "false"

您会注意到,JavaScript 不区分数字类型;数字就是数字,只不过具有不同格式。

JavaScript 还支持通用对象,它本身具有实例类型,比如 Array,如清单 4 所示:

清单 4. Array 的实例
> var myArray = ["Hello", 1, true]
> typeof myArray
"object"
> myArray instanceof Array
true

JavaScript 中的 Arrays 更像其他语言中的列表:可不必限制大小来进行创建,可以保存任何您输入的内容。比如在 Ruby 或者 Groovy 中,JavaScript Arrays 可通过文字语法来创建:[]。更重要的是,就像在其他支持列表的语言一样,希望在 JavaScript Arrays 支持方法(如清单 5 所示):

清单 5. Array 方法
> var myArray = ["Hello", 1, true]
> myArray[0]
"Hello"
> myArray.length
3
> myArray.pop()
true
> myArray
["Hello", 1]
> myArray.pop()
1
> myArray
["Hello"]
> myArray.push("pushed")
2
> myArray
["Hello", "pushed"]

可通过 Array 的位置来获取其值,从零开始。Arrays 支持pushpop 操作,其中 push 增加项目(在其最后一个位置)而 pop 移除项目(就像堆栈,从最后一个开始)。

Arrays 还支持迭代,如清单 6 所示:

清单 6. 通过 Array 迭代
> var myArray = [1,2]
> for(var i = 0; i < myArray.length; i++) { console.log(myArray[i]) }
1
2

类型强制

JavaScript 不仅是一个弱类型的语言 — 它比 Ruby 或者 Groovy 更弱 !JavaScript 可强制变量在代码的特定位置为任何类型。这符合 JavaScript 最初设想:Web 页面交互。JavaScript 不应草率地禁止用户读取在线文章!

类型强制不仅限于 JavaScript,但是 JavaScript 的特点是非常灵活。这是好事还是坏事,取决于您怎么看。JavaScript 的松散可能会隐藏缺陷,就像全局变量一样。

例如,先定义 Array 然后无意中尝试用于进行一些数字操作,甚至是一些 String 级联,如清单 7 所示:

清单 7. JavaScript 类型的灵活性
> var myArray = [1,2]
> console.log(2 * myArray)
> console.log("A" + myArray)

在本例中,第一个日志消息将会打印 NaN,而第二个将会打印 A1,2。在两个例子中,该代码能 “正常运行”,因为没有任何错误发生 — JavaScript 只是不停地运转。这是极端情况下的弱类型。Ruby 中同样的代码不会这样运行,如清单 8 所示:

清单 8. Ruby 不采用那种方式
> array = ["A", "B"]
> ans = 2 * array

清单 8 中的 Ruby 代码将会出错:

TypeError: Array
can't be coerced into Fixnum

如果尝试向 array 增加 "A",情况将是:

TypeError: can't convert
Array into String

如果在 Groovy 中尝试相同的操作,将会得到如下结果:

groovy.lang.MissingMethodException: No signature of method: 
java.lang.Integer.plus() is applicable for argument types: (java.util.ArrayList) values:
[[A, B]]

因此,您可以在操作中看到不同层面的弱类型。显而易见,如果有一个度量类型强弱的标准,JavaScript 将会是它们当中最弱的!


JavaScript 函数

JavaScript 函数,类似于 Java 方法,是用于定义和封装可重用行为的结构。JavaScript 中的函数看上去很像 Groovy 的闭包。在 JavaScript 中的函数是对象。事实上,他们是第一类对象,不像 Java 代码中的方法。因为 JavaScript 函数是对象,所以它可传递给其他函数,并可被调用。

利用 function 关键字来定义函数。就像 Java 语言中的方法声明一样,可以指定参数,还可从 JavaScript 函数返回一些内容。与动态语言不同,比如 Groovy 或者 Ruby,其中返回调用是可选的(这样任何方法的最后一行将返回),如果想要得到返回值,JavaScript 的函数中必须使用 return 语句;否则,将不会返回值。

可以像在 Groovy 中调用闭包一样来在 JavaScript 中调用函数。在清单 9 中,定义了一个没有参数的简单函数。其目的是在 Chrome 的 JavaScript 控制台中打印 “blah”。

清单 9. 在 JavaScript 中定义并调用函数
> function blah() { console.log("blah"); }
> blah() //prints blah
> blah.call() //prints blah
> blah.apply() //prints blah

可通过方法 call 或者方法 apply 直接调用有括号(也就是 ())的函数。在这里展示了首个无类函数对象。清单 10 展示了在函数 blah 中调用 garbage 方法时的情形:

清单 10. JavaScript 中函数作为对象
> blah.foo()

在本例中,错误消息说明 foo 不是一个定义的方法,像这样:

TypeError: Object function blah() { console.log("blah"); } has no method 'foo'

现在再次读取错误消息。看到 foo 不是 已定义的,这意味着如果它 定义,一切就会正常。


JavaScript 中的类

JavaScript 支持原语,我们曾讨论过。它也支持对象,比如 Array。JavaScript 不支持类 — 至少在经典 Java 语言中不支持。因为 JavaScript 是基于原型的语言,您不能定义类:相反,通过克隆 现有对象来重用行为。因此,在 JavaScript 中,不定义类对象,而在函数中进行定义,然后利用嵌套函数来定义行为 — 有些已在运行中见过。

想要模拟一个类,您必须定义一个函数。可以给其一个名称(也就是一个类名),指定参数(和在构造函数中一样),甚至可以使用关键字 .this,这意味着在函数范围内引用变量。更何况,内部函数可以具有别名,看上去像方法调用一样。

为了进行说明,在清单 11 中,我将创建一个 Message 原型(也称为一个类),这非常简单。我将提供一些参数(消息从何处来,发给谁,以及消息本身),而且该类将会以 JSON 格式呈现该消息。

清单 11. JavaScript 中函数作为类
function Message(to, from, msg){
 this.to = to;
 this.from = from;
 this.msg = msg;

 this.asJSON = function(){
  return "{'to':'" + this.to + "', 'from':'" + this.from + "', 'message':'" +
    this.msg + "'}";
 }
}

清单 11 中,我定义了一个 Message 函数 — 带有一个名字和几个属性的对象;即,tofrom、和 msg。然后我定义了一个属性(asJSON)指向内部函数,其任务是将 JSON 消息用字符串表示。

注意,还可在 Web 页面中定义该 “类”,利用 Chrome 来进行加载,打开 JavaScript 控制台,并交互式地进行使用。这就是清单 12 所述的:

清单 12. 在 JavaScript 中使用类
> var message = new Message('Andy', 'Joe', 'Party tonight!');
> message.asJSON();
"{'to':'Andy', 'from':'Joe', 'message':'Party tonight!'}"

此代码很像 Groovy 代码,甚至像 Java 代码(如果不考虑 var),不是吗?实际上,完全可以利用 OOP 技术来构建 JavaScript 应用程序(也就是,程序包含带有数据和相互交互方法的对象)。


结束语

我希望这篇文章能够推翻早已过时的 JavaScript 语言无用论。事实上,它的功能十分强大,而且具有很多语法糖,可以像 Groovy 和 Ruby 之类新的语言一样方便。在 90 年代使得 JavaScript 流行的一些特性,在今天也是可取的。

鉴于 Web 对越来越多的 Java 应用程序开发的重要性,以及 JavaScript 作为浏览器兼容语言的独特地位,每个 Java 程序员都应当熟悉 JavaScript。 浏览器(不论是在计算机中,或者在移动设备、电话、或者平板电脑中)是越来越多用户与应用程序交互的方法。JavaScript 是所有服务器端语言中最常见的媒介。此外,对 JavaScript 有一定理解,将会使您成为任何语言领域(包括您最熟悉的语言)的一名优秀的程序员。

参考资料

学习

获得产品和技术

讨论

  • 加入 developerWorks 中文社区。查看开发人员推动的博客、论坛、组和维基,并与其他 developerWorks 用户交流。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology, Web development
ArticleID=751745
ArticleTitle=Java 开发 2.0: 面向 Java 开发人员的 JavaScript
publish-date=08102011