NODE JS && COFFEE CUP 学习

第一部分 NODE JS 是什么?

选摘自:Michael AbernethyNode.js 究竟是什么?

Node 旨在解决什么问题?

Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”。当前的服务器程序有什么问题?整个 Web 应用程序架构(包括流量、处理器速度和内存速度)中的瓶颈是:服务器能够处理的并发连接的最大数量。

Node 解决这个问题的方法是:更改连接到服务器的方式。每个连接发射一个在 Node 引擎的进程中运行的事件,而不是为每个连接生成一个新的 OS 线程(并为其分配一些配套内存)。Node 声称它绝不会死锁,因为它根本不允许使用锁,它不会直接阻塞 I/O 调用。Node 还宣称,运行它的服务器能支持数万个并发连接。

Node 如何工作?

Node 本身运行 V8 JavaScript。服务器上的 JavaScript。

V8 JavaScript 引擎是 Google 用于其 Chrome 浏览器的底层 JavaScript 引擎。很少有人考虑 JavaScript 在客户机上实际做了些什么?实际上,JavaScript 引擎负责解释并执行代码。Google 使用 V8 创建了一个用 C++ 编写的超快解释器,该解释器拥有另一个独特特征;您可以下载该引擎并将其嵌入任何 应用程序。V8 JavaScript 引擎并不仅限于在一个浏览器中运行。因此,Node 实际上会使用 Google 编写的 V8 JavaScript 引擎,并将其重建为可在服务器上使用。

事件驱动编程

许多程序员接受的教育使他们认为,面向对象编程是完美的编程设计,这使得他们对其他编程方法不屑一顾。Node 使用了一个所谓的事件驱动编程模型。

清单 1. 客户端上使用 jQuery 的事件驱动编程

				
// jQuery code on the client-side showing how Event-Driven programming works

// When a button is pressed, an Event occurs - deal with it
// directly right here in an anonymous function, where all the
// necessary variables are present and can be referenced directly
$("#myButton").click(function(){
     if ($("#myTextField").val() != $(this).val())
         alert("Field must match button text");
});

实际上,服务器端和客户端没有任何区别。没错,这没有按钮点击操作,也没有向文本字段键入的操作,但在一个更高的层面上,事件正在 发生。一个连接被建立,这是一个事件!数据通过连接进行接收,这也是一个事件!数据通过连接停止,这还是一个事件!

为什么这种设置类型对 Node 很理想?JavaScript 是一种很棒的事件驱动编程语言,因为它允许使用匿名函数和闭包,更重要的是,任何写过代码的人都熟悉它的语法。事件发生时调用的回调函数可以在捕获事件处进行编写。这样可以使代码容易编写和维护,没有复杂的面向对象框架,没有接口,没有过度设计的可能性。只需监听事件,编写一个回调函数,其他事情都可以交给系统处理!

 

它对什么有好处?

正如您此前所看到的,Node 非常适合以下情况:在响应客户端之前,您预计可能有很高的流量,但所需的服务器端逻辑和处理不一定很多。Node 表现出众的典型示例包括:

  • RESTful API

    提供 RESTful API 的 Web 服务接收几个参数,解析它们,组合一个响应,并返回一个响应(通常是较少的文本)给用户。这是适合 Node 的理想情况,因为您可以构建它来处理数万条连接。它仍然不需要大量逻辑;它本质上只是从某个数据库中查找一些值并将它们组成一个响应。由于响应是少量文本,入站请求也是少量的文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的 API 需求。

  • Twitter 队列

    想像一下像 Twitter 这样的公司,它必须接收 tweets 并将其写入数据库。实际上,每秒几乎有数千条 tweet 达到,数据库不可能及时处理高峰时段所需的写入数量。Node 成为这个问题的解决方案的重要一环。如您所见,Node 能处理数万条入站 tweet。它能快速而又轻松地将它们写入一个内存排队机制(例如 memcached),另一个单独进程可以从那里将它们写入数据库。Node 在这里的角色是迅速收集 tweet,并将这个信息传递给另一个负责写入的进程。想象一下另一种设计(常规 PHP 服务器会自己尝试处理对数据库本身的写入):每个 tweet 都会在写入数据库时导致一个短暂的延迟,因为数据库调用正在阻塞通道。由于数据库延迟,一台这样设计的机器每秒可能只能处理 2000 条入站 tweet。每秒处理 100 万条 tweet 则需要 500 个服务器。相反,Node 能处理每个连接而不会阻塞通道,从而能够捕获尽可能多的 tweets。一个能处理 50,000 条 tweet 的 Node 机器仅需 20 台服务器即可。

  • 电子游戏统计数据

    如果您在线玩过《使命召唤》这款游戏,当您查看游戏统计数据时,就会立即意识到一个问题:要生成那种级别的统计数据,必须跟踪海量信息。这样,如果有数百万玩家同时在线玩游戏,而且他们处于游戏中的不同位置,那么很快就会生成海量信息。Node 是这种场景的一种很好的解决方案,因为它能采集游戏生成的数据,对数据进行最少的合并,然后对数据进行排队,以便将它们写入数据库。使用整个服务器来跟踪玩家在游戏中发射了多少子弹看起来很愚蠢,如果您使用 Apache 这样的服务器,可能会 有一些有用的限制;但相反,如果您专门使用一个服务器来跟踪一个游戏的所有统计数据,就像使用运行 Node 的服务器所做的那样,那看起来似乎是一种明智之举。

 

Node Package Module

Node 的一个特性是 Node Package Module,这是一个内置功能,用于安装和管理 Node 模块。它自动处理依赖项,因此您可以确定:您想要安装的任何模块都将正确安装并包含必要的依赖项。它还支持将您自己的模块发布到 Node 社区,假如您选择加入社区并编写自己的模块的话。您可以将 NPM 视为一种允许轻松扩展 Node 功能的方法,不必担心这会破坏您的 Node 安装。同样,如果您选择深入学习 Node,那么 NPM 将是您的 Node 解决方案的一个重要组成部分。

 

结束语

Node 是一个程序,能够完成 Apache 能够完成的所有任务(借助一些模块),而且,作为一个可以将其作为基础进行构建的可扩展 JavaScript 平台,Node 还能完成更多的任务。

Node 完成了它提供高度可伸缩服务器的目标。它使用了 Google 的一个非常快速的 JavaScript 引擎,即 V8 引擎。它使用一个事件驱动设计来保持代码最小且易于阅读。所有这些因素促成了 Node 的理想目标,即编写一个高度可伸缩的解决方案变得比较容易。

 

学习

  • Node.js 主页 是了解这个应用程序的切入点。
  • 在这里下载 Node.js。您还将需要 Python
  • 浏览 Node.js API 页。注意,不同发布的语法可能不同,因此,请仔细检查您已下载的版本和正在浏览的 API。
  • 参见 Node 模块页,该页列出了所有可用于 Node 中的模块。
  • 搜索 NPM,轻松扩展您的 Node 安装的功能。

 

第二部分 使用 node.js 进行服务器端 JavaScript 编程

 

作者:成 富  (居然是个湖南老乡 北京 - 韶山 - 北京,MARK一下,http://www.cheng-fu.com

 

模块化结构

node.js 使用了 CommonJS 定义的模块系统。不同的功能组件被划分成不同的模块。应用可以根据自己的需要来选择使用合适的模块。每个模块都会暴露一些公共的方法或属性。模块使用者直接使用这些方法或属性即可,不需要关系模块内部的实现细节。除了系统预置的多个模块之外,应用开发团队也可以利用这个机制来将应用拆分成多个模块,以提高代码的可复用性。

使用模块

在 node.js 中使用一个模块的方式是非常简单的。使用某个模块之前需要首先声明对它的依赖。在 JavaScript 代码中可以直接使用全局函数 require() 来加载一个模块。如 require("http") 可以加载系统预置的 http 模块。而 require("./myModule.js") 用来加载与当前 JavaScript 文件同一目录下的 myModule.js 模块。如果使用 require() 的路径以“/”开头的话,则认为是模块 JavaScript 文件在操作系统上的绝对路径。如果不是这两种情况的话,node.js 就会尝试在当前 JavaScript 文件的父目录及其祖先目录下的 node_modules目录下查找。比如目录 /usr/home/my.js 中调用了 require("other.js") 的话,node.js 会依次尝试查找下列文件:/usr/home/node_modules/other.js/usr/node_modules/other.js/node_modules/other.js

require() 方法的返回值是该模块所暴露出来的公开 JavaScript 对象,包含了可供使用的方法和属性。代码清单 2 给出了模块的基本使用方式。

清单 2. 模块的基本使用方式

 var greetings = require("./greetings.js"); 
 var msg = greetings.sayHello("Alex", "zh_CN"); 
 process.stdout.write(msg);

代码清单 2 所示,一般是直接把 require() 方法的返回值赋值给一个变量,在 JavaScript 代码中直接使用此变量即可。greetings.js 模块暴露了一个 sayHello() 方法,当前 JavaScript 代码直接使用了该方法。

 

事件驱动

开发过 Web 应用的人都熟悉浏览器中的事件处理机制。当对某个 DOM 元素上的某类事件感兴趣的时候,只需要在该 DOM 元素上面注册一个事件监听器即可。如 ele.addEventListener("click", function() {}) 就添加了一个对 click 事件的监听器。当事件发生的时候,事件监听器的 JavaScript 方法就会被调用。事件的处理方法是异步执行的。这种异步执行的方式非常适合于开发高性能并发网络应用。实际上,目前的高性能并发应用开发一般有两种做法:第一种是使用多线程的机制,另外一种就是采用基于事件驱动的方式。多线程的问题在于应用开发起来难度较高,很容易出现线程饥饿或是死锁等问题,对开发人员提出了更高的要求。而事件驱动的方式则更加灵活,很容易为 Web 开发人员所理解和使用,也不存在线程死锁等问题。依托于性能强大的 Google V8 引擎和先进的事件 I/O 架构,node.js 可以成为创建高性能服务器端应用的良好基础。

基于 node.js 开发应用与开发 Web 应用有相似的编程模型。很多模块都会暴露出一些事件,使用这些模块的代码通过注册事件监听器的方式来添加相应的处理逻辑。代码清单 4 中给出了一个简单的 HTTP 代理服务器的实现代码。

清单 4. HTTP 代理服务器

 var http = require("http"); 
 var url = require("url"); 

 http.createServer(function (req, res) { 
    var urlObj = url.parse(req.url, true); // 获取被代理的 URL 
    var urlToProxy = urlObj.query.url; 
    if (!urlToProxy) { 
        res.statusCode = 400; 
        res.end("URL 是必须的。"); 
    } 
    else { 
        console.log("处理代理请求:" + urlToProxy); 
        var parsedUrl = url.parse(urlToProxy); 
        var opt = { 
            host : parsedUrl.hostname, 
            port : parsedUrl.port || 80, 
            path : (parsedUrl.pathname || "") + (parsedUrl.search || "") 
                + (parsedUrl.hash || "") 
        }; 
        http.get(opt, function(pres) { // 请求被代理 URL 的内容
            res.statusCode = pres.statusCode; 
            var headers = pres.headers; 
            for (var key in headers) { 
                res.setHeader(key, headers[key]); 
            } 
            pres.on("data", function(chunk) { 
                res.write(chunk); // 写回数据
            }); 
            pres.on("end", function() { 
                res.end(); 
            }); 
        }); 
    } 
 }).listen(8088, "127.0.0.1"); 

 console.log("代理服务器已经在 8088 端口启动。");

整个代理服务器的实现比较简单。首先通过 http 模块中的 createServer() 方法用来创建一个 HTTP 服务器,再通过 listen() 方法就可以让该 HTTP 服务器在特定端口监听。在 createServer() 方法中传入的参数是 HTTP 请求的响应方法。实际上,每个 HTTP 请求都是对应于 HTTP 服务器上的一个 request 事件。代码清单 4 中的 HTTP 服务器创建部分实际上等价于 代码清单 5 中给出的实现方式。

清单 5. 使用事件机制的 HTTP 服务器创建方式

 var server = http.createServer(); 
 server.on("request", function(req, res) { 
 });

在请求的处理方法里面,通过 http.get() 方法来获取被代理 URL 的内容。这里同样采用了基于事件的处理方式。pres.on("data", function(chunk) {})presdata 事件上添加了一个处理方法。该方法的作用是当获取到被代理 URL 的内容的时候,就把获取到的内容写回到原始 HTTP 请求的响应中。对于 end 事件的处理也是同样的。在使用 node.js 进行开发的时候,会经常遇到这种使用事件处理方法和回调方法的场景。

 

第三部分:JavaScript 现代特性 (与java、groovy、ruby比较)

 

Andrew Glover, 作家和开发人员, Beacon50 Java 开发 2.0: 面向 Java 开发人员的 JavaScript

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

 

在 Chrome 中使用 JavaScript: F12

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

本人注:调试以下程序清单更好的方式是用node.js 提供的node命令行工具。cmd > node

 

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 可通过文字语法来创建:[]。更重要的是,就像在其他支持列表的语言一样,希望在 JavaScriptArrays 支持方法(如清单 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 有一定理解,将会使您成为任何语言领域(包括您最熟悉的语言)的一名优秀的程序员。

 

扩展阅读:

JavaScript 开发工具包 http://www.ibm.com/developerworks/cn/web/lp/jstoolkit/

 

第四部分:CoffeeScript

摘自: http://article.yeeyan.org/view/260164/251745    你的第一杯CoffeeScript,第1部分:入门 

The Little Book on CoffeeScript - 语法

island205 本文译自The Little Book on CoffeeScript的第1章。该书是GitHub上的一个开源项目,采用MIT授权协议。遂将其翻译过来,以便方便更多人接触CoffeeScript,沿用MIT授权协议。译文有不妥之处,请指正。

 

CoffeeScirpt是什么?

CoffeeScript是一门小巧的语言,会编译为JavaScript。它的语法风格受到了Ruby和Python影响,很多特性都借鉴于这两种语言。我们写作本书的目的在于帮助你学习CoffeeScript,明白最佳实践是什么,以及帮助你开始创建有意思的客户端程序。这本书很小,仅仅只有五章,但是对与CoffeeScript这门小语言来说已足够。

CoffeeScript*不是*JavaScript的超集,因此尽管你可以在CoffeeScript中的使用外部的JavaScript类库,但是如果你在没有转化之前而直接编译当前的JavaScript的话,会出现语法错误。编译器会把CoffeeScript代码转化为相对于的JavaScript,这样在运行时就不需要解释了。

首先澄清一些误解。由于处理运行时错误需要JavaScript相关的知识,要写CoffeeScript就得了解JavaScript。但是话说回来,运行时错误通常比较明显,并且到目前位置,我没觉得从JavaScript映射到CoffeeSCript会有什么问题。第二个问题是我经常听到CoffeeScript相关的话题是速度。即,CoffScript编译后的JavaScript运行起来相比与之等价的纯JavaScript代码要慢。但实际情况证明并不是问题。CoffeeScript看起来与徒手写的JavaScript代码运行速度相当,甚至更快。

CoffeeScript的劣势是什么?是的,在你和JavaScript之间介多了编译这一步。CoffeeScript也在尝试尽力通过产生优雅的可读性强的JavaScript,以及在服务器端集成自动编译来弥补这个问题。另外一个缺陷是,作为一个新的语言,事实上现阶段社区也还比较小,想找个懂这门语言的合伙人会花费你的大量你的时间。当然,CoffeeScript发展迅猛,相关的IRC列表也是人才济济,如果你有什么问题的话,都会得到迅速的解答。

CoffeeScript的用途并不仅限于浏览器,把它用在JavaScript实现的服务端也非常不错,比方说在 Node.js上。还有,CoffeeScript越来越广泛,有更多的集成,比方说它已经是Rails3.1的标配。现在正是进入CoffeeScript学习的时机。你现在为学习这门语言付出的时间在以后会以为你节约大量的时间作为回报的。

 

安装

你是否曾希望能够通过命令行来运行JavaScript?反正我是没有,不过CoffeeScript可能会改变现状。有了Node.js,你可以通过命令行来运行JavaScript,或是把JavaScript作为执行脚本的组成部分来运行。Node.js的这一主要功能允许在命令行上执行CoffeeScript代码,其提供了(使用CoffeeScript编写的)CoffeeScript编译器所需要的运行时。

第一步是安装Node.js,有几种安装选择;你可以编译源代码,或是运行可用于各种系统的安装程序之一。通过命令行运行node -v来确认Node.js已经安装并且已位于路径中。

Node.js给你带来了一个额外的收获:节点包管理器(NPM)。通过命令行运行npm -v确认NPM已经安装并已位于路径中之后,就可以按照如下步骤来使用NPM安装CoffeeScript了。

1. 通过命令行运行npm install --global coffee-script。
--global标记让CoffeeScript可为全系统所用而不仅是为某个特定项目所用。

D:\work\js>npm install --global coffee-script
npm http GET https://registry.npmjs.org/coffee-script
npm http 200 https://registry.npmjs.org/coffee-script
npm http GET https://registry.npmjs.org/coffee-script/-/coffee-script-1.2.0.tgz
npm http 200 https://registry.npmjs.org/coffee-script/-/coffee-script-1.2.0.tgz
C:\Users\Administrator\AppData\Roaming\npm\coffee -> C:\Users\Administrator\AppD
ata\Roaming\npm\node_modules\coffee-script\bin\coffee
C:\Users\Administrator\AppData\Roaming\npm\cake -> C:\Users\Administrator\AppDat
a\Roaming\npm\node_modules\coffee-script\bin\cake
coffee-script@1.2.0 C:\Users\Administrator\AppData\Roaming\npm\node_modules\coff
ee-script


2. npm命令应该输出诸如/usr/bin/coffee -> /usr/lib/node_modules/coffee-script/bin/coffee一类的信息。
NPM在 /usr/bin中创建了一个快捷方式,所以现在coffee这一可执行文件就处在正确的路径中了,这是CoffeeScript的编译器和解释器。
3. 若要验证coffee这一执行文件已位于路径中,通过命令行运行coffee -v。

还剩最后一步来确认CoffeeScript的环境已被正确设置。为了让CoffeeScript对于任何启动的Node.js进程来说都是可用的,你需要把它加入到Node.js所谓的NODE_PATH中,在遇到未识别的函数时,Node.js会通过搜索NODE_PATH来获取一些模块(库)。

就本文中的例子来说,主要是把Node.js用作CoffeeScript可执行文件的运行时。最容易的做法是简单地把所有的NPM模块都添加到NODE_PATH中,若要找出NPM模块所处的位置,输入 npm ls -g,你需要添加一个把NODE_PATH指向这一位置的环境变量。例如,如果npm ls -g的输出是/usr/lib,则模块位于/usr/lib/node_modules目录下,若要设置一个NODE_PATH环境变量,运行export NODE_PATH=/usr/lib/node_modules。

你可以通过把上面的命令放入到启动脚本(比如说~/.bash_profile)中来进一步简化这些事情。若要验证所做的修改,执行Node来启动一个Node.js外壳程序,然后输入require('coffee-script'),Node.js外壳程序应该就会载入CoffeeScript库。如果执行没问题的话,CoffeeScript环境就是随时可用的了。现在你可以从编译器开始,启动CoffeeScript的探索之旅了。

posted @ 2012-03-17 01:09  喻头快跑  阅读(1692)  评论(0编辑  收藏  举报