idea中如何使用coffeescript 语法编辑器。

收藏,90 浏览
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
Javascript:
for (name in attr) {
console.log(attr[name])
如果用 CoffeeScript 写成这样:
for name in attr
console.log attr[name]
就运行不成功,请问该如何去遍历这个哈希数组?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
11月8日 回答
for key, value of attr
console.log attr[key]
console.log value
咋不看文档呢,又不长。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
11月8日 回答
for in 用在数组,直接返回 value
for x in ['a','b','c','d','e'] then console.log x
for of 即可数组,也可对象,返回 key:value
for x,y of {'a':'b'} then console.log "#{x}:#{y}"
以上的代码也可写成这样:
['a','b','c'].forEach (value)-&console.log value
回答,投票,评论
第三方账号登录,无需注册,即刻开始
举报理由:
带有人身攻击、辱骂、仇恨等违反条款的内容
与已有问题重复
内容质量差,或不适合在本网站出现
答非所问,不符合答题要求
其他原因(请补充说明)
补充说明:聊聊为何不在项目中使用 CoffeeScript 与 Less (zihua.li) - 推酷
聊聊为何不在项目中使用 CoffeeScript 与 Less (zihua.li)
这篇日志将以偏技术的角度介绍我最近在做的业余项目 Code Game,其中我会解释 Code Game 对某些技术是如何进行取舍的,包括为什么不使用 CoffeeScript 以及选择 Myth 代替 Less/Sass 的原因。
Code Game 是什么
Code Game 是我花费一个月的业余时间完成的 AI 脚本对战平台,网址是
,玩家可以通过编写 JavaScript 脚本来控制游戏中的角色并与平台上的其他玩家进行竞赛。
Code Game 的灵感来源于大学时我在北航 MSTC(Microsoft Technology Club) 参与的 BigTank 项目。BigTank 是一个使用 C# 开发的 3D 坦克对战游戏,与传统坦克对战游戏由玩家直接操控坦克不同,BigTank 的玩家需要通过编写 Lua 脚本来分析游戏局势并控制自己的坦克行动,本质上是一个关于 AI 算法的 Online Judge 平台。基于 BigTank,MSTC 举办了编程挑战赛,在北航获得了很好的反响。可惜限于开发周期和当时的技术水平,BigTank 本身存在很多不足,包括游戏规则欠考虑、脚本解析器存在不少 Bug 等,种种这些都或多或少地影响了比赛的精彩程度。一个月前,我终于决定重新开发一套类似 BigTank 的平台来弥补遗憾。
Code Game 的页面构成很简单,挨个介绍也并不会花费很多篇幅。用户使用 GitHub 账号登录网站会进入个人主页页面,在这个页面中玩家可以看到自己的资料和 AI 的排名:
点击“编写我的 AI”按钮就来到了脚本编写页面,该页面由支持代码高亮和自动补全的在线编辑器、可以实时看到脚本的运行效果的预览画面以及用来查看调试信息的控制台组成:
Code Game 每天会根据 AI 的胜率更新一次排行榜,通过排行榜可以看到每个玩家的排名,并且点击昵称可以进入其个人主页:
玩家可以在他人的个人主页向对方发起挑战,发起挑战后玩家会进入挑战页面,并看到两个脚本的对战情况,游戏结束后页面会告知玩家胜者及胜利原因:
Code Game 的技术架构以及对技术的取舍理念是优先考虑开发效率,并在保证运行效率可接受的前提下尽量降低技术栈复杂度。
1. 开发语言
Code Game 使用
开发,除了我对其较熟悉以外,选择 Node.js 的另一个重要原因就是使用 Node.js 实现 JavaScript 脚本沙盒相较其他语言要容易得多。
2. 前端技术栈
前端使用了
,下面分别详细介绍。
Gulp 平常的开发中,对于小型项目我一般会使用 Make 或 NPM 的 scripts 来进行构建任务。而 Code Game 由于需要构建的内容较多,所以选择了 Gulp。相较于更为流行的 Grunt,Gulp 的 Stream 理念使得完成同样的构建任务时编写的代码更少。在 Code Game 中,Gulp 中的任务分为两类:一类任务用来实现检测源文件的改动并自动编译,比如将基于 Myth 编写的 CSS 实时编译为可以被浏览器解析的 CSS;另一类任务则用来执行生产环境的构建,比如合并 CSS、压缩 JavaScript 等。
Myth 在各种 CSS 预处理语言中绝对算不上流行,在 GitHub 上其共被 3000 余人 star,虽然不算少,但相比 Less 这样动辄一万多 star 的项目说是冷门也毫不过分。Myth 的优势和它的口号一样:“CSS the way it was imagined.” Myth 可以让你提前使用 CSS 的高级特性而无需考虑浏览器兼容问题。举例来说,当用到 transform 属性时通常还需要额外加上浏览器前缀 -webkit 来兼容 Safari 和 旧版的 Chrome,如果要兼容 IE 9,则更是要加上 -ms 。而使用 Myth 则不用操心这个问题:只需要写一个 transform ,Myth 会在编译过程中自动加上需要的前缀。Myth 与 Less、Sass 这样的预处理语言最大的区别就在于写 Less 时你是在写 Less,写 Sass 时你是在写 Sass,而当你写 Myth 时,你就是在写 CSS。这一点十分重要,因为把标准和草案都算上,CSS 语言本身已经足够完备了,它支持变量:
--purple: #847AD1;
--large: 10px;
color: var(--purple);
padding: var(--large);
} 也支持数学计算: pre {
margin: calc(var(--large) * 2);
} 甚至还支持颜色处理: a {
color: var(--purple);
color: color(var(--purple) tint(20%));
} 可以说需要用到的特性 CSS 本身就已经具备了,那么何必再使用另一种语言呢?更何况 Less 和 Sass 这样“强大”的预处理语言在带来开发上方便的同时也引入了很多问题,而大部分问题都可以归结到一点,即“你根本就不是在写 CSS”。看下面的 Less 代码: .container {
width: 960px;
overflow: hidden;
width: 61.8%;
float: left;
background: #f00;
position: absolute;
background: url(&images/header-image.jpg&);
Less 支持的样式嵌套很容易诱使开发者写出上面这样层层嵌套的代码,编译成 CSS 后,最长的 Selector 是 .container .main .post .title ,以纯 CSS 的眼光来看,应该减少嵌套层数来提高性能(比如改成 .post .title ),亦或是优化类名来实现样式模块化(比如把 .post .title 改成 .post-title )。然后一旦用 Less 写出来,就很难以 CSS 的角度来审视本就要编译成 CSS 的代码。很多使用 Less 或 Sass 的公司的 Style Guide 都会明确禁止过度嵌套,然而与其以规范来要求开发者,不如就单纯地使用 CSS,并享受 Myth 提供的便利来的方便自然。
Browserify
Browserify 可以非常方便地实现前端 JavaScript 的模块化。使用 Browserify,你可以在前端的 JavaScript 中使用和 Node.js 一样的模块加载方式,即 require('modules') ,使得前后端 JavaScript 模块级复用成为了可能。Code Game 游戏沙盒部分的所有模块曾经是前后端共用的,当用户在编辑器中预览时沙盒运行在前端,当与其他玩家竞赛时,沙盒则运行在后端。同时 Browserify 作为一个构建工具,并不影响前端脚本的加载逻辑,换言之在使用 Browserify 的同时依然可以使用 RequireJS、SeaJS 这样的 Module Loader 以及 Combo Handler 等技术。
除了 Browserify 以外,Code Game 没有使用其他的 JavaScript 预处理工具。也没有使用
这样的语言替代 JavaScript,原因在于 JavaScript 在前端工程方面本身已经足够优秀,而 CoffeeScript 和 LiveScript 这样的语言在提供更“现代”的语法同时,也会大大降低代码的可控性。同 Less 和 CSS 的关系一样,CoffeeScript 与 JavaScript 在语言层面的差异会导致二者间代码逻辑的不调和。一个最明显的例子是 CoffeeScript 提供的 class 关键词使得其可以像 基于对象 的语言一样声明类,然而 JavaScript 本身却是是 基于原型 的语言,当一个以基于对象的思想编写的代码逻辑编译成基于原型的语言时,其间产生的落差已经不是语言之间的优劣可以衡量的了。更何况 CoffeeScript 语言本身就存在太多的问题,比如 CoffeeScript 的函数调用无需写 () ,使得易读性大为下降(比较 console.log x + 1 和 console.log x +1 ),同时也引入了很多细节问题(比如无法实现 JavaScript 里的具名匿名函数 invoke(function func() {}) ),另外 CoffeeScript 生成的 JavaScript 虽然有很多最佳实践,但总体并不易读,也很容易生成冗余代码,比如:
greet = (name) -&
for time in ['morning', 'afternoon', 'nignt']
console.log &Good #{time}, #{name}!&
greet 'Bob' 会生成: var greet;
greet = function(name) {
var time, _i, _len, _ref, _results;
_ref = ['morning', 'afternoon', 'nignt'];
_results = [];
for (_i = 0, _len = _ref.length; _i & _len; _i++) {
time = _ref[_i];
_results.push(console.log(&Good & + time + &, & + name + &!&));
return _results;
greet('Bob');
虽然语句表达式化是好的,免去写 return 也是好的,但是 CoffeeScript 终究还是一门要编译成 JavaScript 的语言,本来简单的代码变得如此复杂,即使表面再光鲜又有什么意义呢。CoffeeScript 对于初级 JavaScript 程序员来说,可以帮助他们避免很多 JavaScript 的陷阱,也能更顺畅地写出最佳实践的代码,但从整体而言,一个富有经验的 JavaScript 开发者写出的 JavaScript 更可能要比 CoffeeScript 的可控性来的高。
SketchTool 之前做设计一直使用 Photoshop,直到见识到 Sketch 的威力后便很少碰 Photoshop 了。网上有很多文章讨论两者的设计优劣,所以不再赘述。这里主要介绍对开发者来说 Sketch 的优势。 相较 Photoshop,Sketch 最大的优势就是可以实现切图自动化,对于每个图层来都可以指定其导出格式以及文件名:
更重要的是,Sketch 官方提供了命令行工具 SketchTool,可以通过命令将 Sketch 源文件按规则导出成图像文件,这意味着配合 Gulp 可以实现当修改 Sketch 的设计后自动切图。同时由于 Sketch 的文件普遍很小,所以甚至可以将其放入版本库中来维护其版本(自然这样也就无需将切好的图片放入版本库,因为这些图片可以由 Gulp 构建脚本生成)。
三、沙盒的实现
在 Code Game 中最关键的一环就是沙盒的实现了。因为涉及到对战,所以比赛时双方选手的代码自然不能运行在前端以免让玩家看到对手的代码。所以 Code Game 采用如下流程来实现脚本对战:
玩家在编辑器调试代码并保存
服务端将玩家的代码保存到 MySQL 数据库中
进行比赛时,服务端调集双方的代码,并在后端解析运行
运行结束后,将游戏“录像”传回前端
前端解析“录像”,并以动画形式展现给用户
下面分三个部分着重介绍 3 和 5 两个过程。
在后端解析玩家代码
这一过程是沙盒的意义所在。因为后端使用 Node.js 开发,而玩家的脚本本身是 JavaScript,所以解析脚本的过程本身就很简单,一个 eval() 即可。然而 eval() 并不能限制用户的脚本权限,从而使得用户的脚本可以访问 Node.js 的各种库函数,也会污染 Node.js 的全局变量,同时也无法对脚本的运行时间进行任何限制。
这个问题的解决方式是使用 Node.js 提供的 script.runInNewContext() 函数。 runInNewContext() 函数接受两个参数:一个是全局变量对象,这个对象包含脚本可以使用的全部全局变量,在脚本中声明的全局变量也会保存在这个对象中;另一个是运行选项,可以在这个参数中指定脚本的超时时间,要注意的是这个参数是从 Node.js 0.11.x 开始支持的。
Code Game 定义了 Sandbox 类:
var Sandbox = module.exports = function(sandbox) {
this.Math = Math;
this.parseInt = parseInt;
for (var key in sandbox) {
if (sandbox.hasOwnProperty(key)) {
this[key] = sandbox[key];
执行玩家脚本时,会实例化一个 Sandbox 实例作为全局变量对象,所以玩家能使用的全局变量只有 Math 和 parseInt 。同时玩家的脚本都会声明一个 onIdle() 函数(具体可以参见
),这个函数可以在之前的 Sandbox 实例 sandbox 中获取到。接下来需要实现在坦克空闲时执行 onIdle() 函数,如果直接调用 sandbox.onIdle() 来执行的话就无法借助 runInNewContext() 函数来实现超时检测了,所以 Code Game 使用如下的方法来解决这个问题:
Player.prototype.onIdle = function(self, enemy, game) {
var code = 'onIdle(__self, __enemy, __game);';
if (!this.script) {
this.script = vm.createScript(code);
var start = Date.now();
this.sandbox.__self = self;
this.sandbox.__enemy = enemy;
this.sandbox.__game = game;
this.sandbox.print = function() {
this.script.runInNewContext(this.sandbox, {
timeout: 1500
} catch (e) {
this.runTime += Date.now() - start;
首先为 __self 、 __enemy 和 __game 这三个不对用户公开的全局变量赋相应的值,之后使用同样的 Sandbox 实例执行代码 onIdle(__self, __enemy, __game) 。因为调用了 runInNewContext() ,所以可以定义超时规则。
录像文件的格式
为了将代码的执行结果在前端展示给用户,最重要的是把结果以一定规则记录下来,形成游戏录像。录像文件中记录了每个对象(坦克、子弹等)在每个帧的位置和执行的动作,如:
&objectId&: &6e723&,
&type&: &tank&,
&direction&: &right&,
&position&: [6, 7],
&action&: &go&,
&objectId&: &4ad3f&,
&type&: &tank&,
&direction&: &left&,
&position&: [10, 2],
&action&: &turn&,
&value&: &left&
&objectId&: &6e723&,
&type&: &tank&,
&direction&: &right&,
&position&: [6, 8],
&action&: &go&
首先录像的最外层是个数组,数组的一个元素代表一帧发生的所有动作。上面的示例录像中,第一帧坦克 6e723 从坐标 (6, 7) 向当前方向(右)前进了一个单位,同时坦克 4ad3f 向左转弯。第二帧坦克 6e723 从坐标 (6, 8) 继续前进了一步,同时坦克 4ad3f 没有执行任何操作。
理论上来说,录像文件中只要记录每个对象最初的状态和中间每步的动作即可使数据完整。然而可以注意到上面的录像样例中的每一帧都会把对象的所有信息记录下来,包括朝向和坐标。这使得前端播放录像时可以从任意一帧开始播放,而不需要从头开始初始化对象状态,另外由于 Code Game 的录像一般都很小(游戏限定 200 帧之内必须结束),所以这样记录从成本考量也可以接受。
前端录像展示
一般而言在前端实现动画有如下几种方式:
通过 JavaScript 操作 DOM
使用 CSS Animation
Canvas 动画
在开发 Code Game 项目时,首先排除的是 Canvas。虽然 Canvas 的性能优异且兼容性良好,但是就播放录像这样简单的需求而言使用 Canvas 开发相对繁琐。其次排除的是直接操作 DOM,因为 JavaScript 实现的动画进行微小的位移时会出现抖动,而 Code Game 开发时希望对战页面可以在移动设备上播放,同时用户可以自定义播放速度,这就使得小位移的动画非常容易出现。
所以最后采取的播放录像的动画方案是 CSS Animation。录像中的每个拥有 objectId 属性的对象都会为其生成 DOM 节点,节点的 ID 由 objectid 构成,同时根据 type 的不同为其赋予不同的背景图。具体的动画实现以下面的动作为例:
&objectId&: &6e723&,
&type&: &tank&,
&direction&: &right&,
&position&: [6, 7],
&action&: &go&,
首先通过 JavaScript 找到 6e723 DOM 节点,然后根据当前游戏的 FPS 和地图大小 修改该节点的 Transition 时间,同时通过 transform 的 translate 操作来移动对象。
这样的实现存在一个问题,假设一个坦克不转向,一直前进了 10 个单位,前端会修改 10 次节点的 transition 和 transform 属性,每次只移动一个单位。而实际上对于这种情况可以优化成只修改一次属性,一次直接前进 10 个单位,当然 transition 的时间也要相应乘以 10。因为在游戏中坦克直线连续行进的地方很多,所以这种优化效果很明显。为此 Code Game 在前端会在解析录像前对录像进行优化,合并直线前进的操作。如上面的录像实例会被优化成:
&objectId&: &6e723&,
&type&: &tank&,
&direction&: &right&,
&position&: [6, 7],
&action&: &go&,
&frames&: 2
&objectId&: &4ad3f&,
&type&: &tank&,
&direction&: &left&,
&position&: [10, 2],
&action&: &turn&,
&value&: &left&
坦克 6e723 在第一帧的动作中增加了 frames: 2 这个属性,表明一共前进了两帧,在之后播放动画时就可以大大降低修改 DOM 属性的次数了。
这篇文章从开发 Code Game 项目的角度介绍了我对 Less/Sass 和 CoffeeScript 这些流行技术的取舍,以及在 Node.js 中开发沙盒的一些经验。然而技术本身其实并没有明显的优劣可言,只有基于特定项目和特定的开发者讨论时,关于“取舍”的话题才有意义。如果大家关于本文有什么想法,欢迎留言讨论。
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读加载中,请稍候...
加载中,请稍候...
京 东 价:
¥29.80 [8.6折][定价:¥35.00]
温馨提示:
其它类似商品
正在加载中,请稍候...
正在加载中,请稍候...
正在加载中,请稍候...
图灵程序设计丛书:深入浅出CoffeeScript
¥29.80 [8.6折]
查找同类商品
作为唯一所有主流浏览器都支持的脚本语言,JavaScript俨然已成为Web开发领域最具号召力的语言,但它的种种语言怪癖以及在各种浏览器间实现不一致等问题也为开发人员所诟病。2009年底,CoffeeScript横空出世。它吸收了JavaScript语言的精华,并添加了很多现代语言脚本的特性,很快便得到了大量Web开发人员的青睐。 《深入浅出CoffeeScript》由CoffeeScript重要贡献者Trevor Burnham操刀,从基础知识入手,全面详尽地介绍了CoffeeScript这门新语言。通过一个5&5拼字游戏,作者将CoffeeScript各方面的知识融入其中,通俗易懂地讲解了CoffeeScript如何与jQuery等非常流行的类库完美集成,如何游刃有余地结合Socket.IO实现Node.js双通道异步通信。每章结尾都有精心设计的习题,有助于读者巩固所学的CoffeeScript知识并更上一层楼。 掌握CoffeeScript,Web开发之旅将更轻松、快捷和优雅!
《图灵程序设计丛书:深入浅出CoffeeScript》是一门新语言,是JavaScript预编译器。由它生成的JavaScript代码能兼容所有浏览器环境,可读性更强、更优雅。《深入浅出CoffeeScript》通过一个贯穿全书的小游戏,从基础知识讲起,全面透彻地介绍了CoffeeScript,并展示了它与jQuery与Node如何搭配运行。
《深入浅出CoffeeScript》适合Web
开发人员及对CoffeeScript感兴趣的读者。
Trevor Burnham,全栈式Web框架开发专家,DataBraid创始人,开源拥趸,技术布道师。
寸志,2011年7月毕业于同济大学信息安全专业,在校期间,曾荣获微软精英大挑战优胜奖,第三届三叶草软件竞赛三等奖等。现任大众点评网前端工程师。热爱互联网,热衷研究新技术,崇尚开源精神,喜欢运动和阅读。
&学习CoffeeScript有助于读者成为更优秀的JavaScript开发人员。而且,本书读来酣畅淋漓,对于准备学习CoffeeScript的新手,这种体会尤为深刻。&
&&Brendan Eich,JavaScript之父
&很难想象现如今会有哪个Web程序没有大量使用JavaScript。如果你用惯了Ruby之类的语言,再使用JavaScript就会明显感觉在退步,这可不是什么愉快的事儿。来看看CoffeeScript吧:它是一个JavaScript预编译器,移除了JavaScript中不必要的冗余,让代码编写和源码阅读变成一件乐事。来,向着Coffee前进吧!这是一本很棒的CoffeeScript入门书。&
&&David Heinemeier Hansson,Ruby on Rails之父
&CoffeeScript是编程语言领域最有意思的进展之一,它吸纳Ruby和Python等语言之精华,是一个极富表现力的语言。本书将指引你进入CoffeeScript的世界;对于那些有志于提高JavaScript开发效率的开发者,本书同样必不可少!&
&&Travis Swicegood,《版本控制之道&&使用Git》作者
安装CoffeeScript
CoffeeScript编辑器
&邂逅&coffee
编译为JavaScript
调试CoffeeScript
函数、作用域和上下文
函数基础知识
访问arguments对象
条件表达式和异常
作用域:你在哪里看到它们
属性参数(@arg)
默认参数(arg=)
参数列(...)
项目:5&5游戏输入分析器
做得好,年轻的学徒
集合与迭代
作为哈希表的对象
JavaScript基础知识:一节JavaScript补习课
精简的JSON
同名键值对
吸收操作符:'a?.b'
切分和剪接
集合的迭代
模式匹配(或解构赋值)
项目:5&5单人游戏
模块:解构程序
原型的威力
类:原型函数
使用extends来继承
项目:重构5&5游戏
Dictionary类
Console.Coffee接口
就如&一勺糖&
Web交互开发
jQuery之道
项目:基于浏览器的5&5游戏
index.html
jq5&5.coffee
未来是jQuery化的
Node.js服务器端程序
什么是Node.js
使用exports和require构建模块化代码
项目:多人5&5游戏
5&5server.coffee
5&5client.coffee
客户端、服务器端--有何不同
运行CoffeeScript的几种方法
JavaScript开发者备忘录
如果你读过前言,那么现在应该已经了解了CoffeeScript是什么,它从何而来,以及它为什么是继Herman Miller牌办公椅之后,对程序员来说最棒的东西了。但是实际上你还没写过一行代码,等不及了是吧?
好,深呼吸下,时候到了。在本章中,我们将在你的操作系统中安装CoffeeScript,配置好编辑器,最后再运行一些代码!
1.1 安装CoffeeScript
CoffeeScript编译器是用CoffeeScript写成的,这就产生了一个先有鸡还是先有蛋的问题:我们是如何在一个还没装CoffeeScript编译器的系统上运行编译器的呢?如果能找到某种方法,在机器上浏览器之外运行JavaScript代码,且允许这些代码访问本地文件系统就好了&&
对,其实我们有Node.js!大家把Node当成一个JavaScript的Web服务器(详见6.1节),但是它可不止这个功能。从根本上讲,它是JavaScript代码和操作系统之间的一个桥梁。Node也有一个名为npm的很棒的工具,即Node包管理器(Node Package Manager) 。如果你是Ruby程序员,可以将其想象为Node版的RubyGems 。npm已经成为安装管理Node程序和类库约定俗成的标准了。
本节的剩余内容讲述Node和npm的安装,有了它们,我们就能够使用CoffeeScript标准的coffee编译器了(我们在第6章同样需要使用Node和npm)。如果你迫不及待地想要实践一下的话,可以访问http://coffeescript.org/,点击&Try CoffeeScript&按钮,然后直接跳到下一章去(要在浏览器中显示console输出,需要某些工具,比如说Fire Lite )。
准备好了?那我们就开始吧。
使用Node.js和npm安装CoffeeScript
尽管有很多不借助Node来运行CoffeeScript代码的方法(附录2会谈到其中几种),然而我还是假定你在全书中用的是标准的coffee命令,专门运行在Node上的。但是只有在第6章才会明确需要使用Node和npm。
请注意,使用Windows系统的用户,在继续之前你需要先安装Cygwin 。Cygwin基本上相当于一个Linux模拟器。虽然Node.js在0.6版本的蓝图中计划直接支持Windows,但是在写作本书之时,使用Cygwin是现有的最可靠的方法。
Mac用户需要安装Xcode ,重点并不在于这个程序,而在于那些随它一起安装的命令行开发工具。尝试运行命令gcc(GNU编译器集合)来检测系统中是否已经安装了这些工具:
如果输出如上所示,那就说明准备就绪了。如果没有的话,那么就请安装Xcode(Mac用户),或者直接安装标准创建工具(Linux或者Cygwin环境下)。
无论是什么系统(Linux/Unix/Mac),现在都配置好标准创建工具了吧?太棒了!现在去访问http:///579814,此处列出的安装方法之多会让你眼花缭乱,它们都出自npm的创建者Isaac Schlueter。对于所有Mac用户,我推荐使用Homebrew 方法(先安装Homebrew)。对于其他系统的用户,列表中的第一个选择则最为直接,也是最好的方式。Node是个很大的程序包,安装它需要花几分钟。
安装好Node之后,运行最新的npm远程安装脚本:
如果你碰到权限错误,可以使用chown 改变Node安装目录的属权(该方法可以减少很多麻烦),也可用sudo sh 替换普通sh。
无论选择哪种方法,都要测试一下node和npm是否已经存在于系统的环境变量PATH中了:
(简单的提一下与版本相关的事情:Node的版本号为偶数时API保持稳定。因此,本书的例子在最新的0.4.x版本下应该运行正常。但是Node 0.5.x版则会以API的变化为重点,而这些变化将会包含到0.6.x稳定版中。说到npm,本书中假定你使用的是npm 1.x。因此,如果你还在使用npm 0.x,是时候升级了。)
现在抓取最新发布的CoffeeScript:
参数-g是--global的缩写,它使已安装好的库在全局系统中都可用(默认情况下,npm install [package]把指定的程序包安装到当前的子目录node_module中,这样便于安装只适用于特定项目的类库)。只要是安装那些包含二进制可执行程序的程序包,我都推荐使用-g参数。
npm install命令的输出结果告诉我们,作为安装包的一部分,两个二进制可执行程序cake和coffee已安装好了。让我们测试下coffee是否已经在系统的PATH 中了:
如果这样不行,那就看一下npm install输出结果中->符号之前的路径(例如/usr/local/bin),然后把它添加到系统的PATH中去。如果使用的是Mac默认bash终端的话,在你的~/.profile文件中添加下面这行代码即可:
注意不要遗漏:$PATH这部分,否则/usr/local/bin会直接替换掉系统的PATH变量,而不是将自己添加到里面!要让这行代码生效,需要保存好文件并且开启一个新的会话终端(比方说,把老的终端关掉打开一个新的)。
如果使用的是其他系统或终端,步骤可能会略有不同,可以输入echo $SHELL搞清楚你使用的是哪个终端。不要忘了在修改完文件之后重新打开会话终端,以便修改生效。
最后一步:就像要想在任何地方都能够使用二进制程序就必须把它们放到PATH中一样,npm安装的Node类库也必须添加到NODE_PATH中。可以输入如下命令查看Node安装类库的位置:
(该命令同时还列出了npm全局安装的所有类库。去掉-g就可以看到安装在当前目录下的所有类库。)我们需要把该路径下的子目录node_module添加到NODE_PATH中。在笔者的系统中,就是将如下内容添加到~/.profile文件中:
同样,你的系统上需要采取的操作步骤可能会有所不同。要测试NODE_PATH是否有效,打开一个新的会话终端输入命令node,即可打开Node.js的REPL &&一个交互式命令运行环境。接着输入:
我保证,这是本书中唯一一行你需要输入的JavaScript代码!
如果NODE_PATH设置得不正确,会看到一个Error: Cannot find module &coffee-script&的错误提示。如果只是看到一段很长的对象描述,那就没有问题了。完成后,可以输入process.exit()或者使用
来退出Node的REPL。
顺便说一下,coffee-script库已经超出了本书的范围;我能说的就是,在CoffeeScript或JavaScript程序中,它能让你把CoffeeScript编译成JavaScript。你可以基于此做一些非常酷的事情,比方说你可以自己写一个包含自定义后期处理的编译器,或者可以写一个像Cakefile 那样的打包脚本。
嘿!我知道安装过程似乎花了很多时间,不过请相信我,既然我们获得了为自己所用的Node和npm的全部能力,那付出终将获得回报。现在让我们来配置下编辑环境吧。
在刀锋上起舞
如果你一定要用最新的CoffeeScript,这实际上也非常容易。只需要使用git 把CoffeeScript的代码仓库克隆下来,然后使用npm从本地目录中安装它即可:
这将安装CoffeeScript当前的master分支,它多少有点不稳定。可以运行如下命令来还原到特定版本的CoffeeScript(比如说1.1.1):
1.2 CoffeeScript编辑器
在https:///jashkenas/coffee-script/wiki/Text-editor-plugins上可以找到一份最新的支持CoffeeScript的编辑器列表。如果你使用的是Mac系统,那我推荐使用由Jeremy Ashkenas维护的TextMate插件 。在撰写本书时,Vim、Emacs、gedit、jEdit以及IntelliJ IDEA也分别有插件提供了对CoffeeScript的支持。
最近,使用基于Web的编辑器编写代码已成为可能,这些编辑器支持实时协作,不依赖于任何特殊的设备。目前对CoffeeScript支持得最好的Web编辑器是安装了Cloud9 Live CoffeeScript Extension 的Could9。
当然,你可以使用任何自己喜欢的编辑器,但是支持CoffeeScript的编辑器会给你带来3大优势&&语法高亮、自动缩进以及内置的编译快捷方式。前两个优点理解起来很容易,但是第三个优点是很多程序员没有好好利用的部分。
在TextMate中,可以使用 R(运行)来运行CoffeeScript文件,或者只用 B(生成)来查看编译后的JavaScript。编译只需几毫秒,因此如果对于一个CoffeeScript表达式如何转化为JavaScript不是很确定,那么快速编译就是搞清楚这一过程的最快方法。如果有被选中的文本,则这些命令仅仅运行选中部分的代码而不是整个文件,这就让测试小块代码以及定位语法错误变得容易多了。如图2所示
图2 直接在TextMate中运行选择的代码
稍微注意下,一些编辑器(包括TextMate)不会默认采用PATH值,这就意味着在你试图运行coffee命令时可能会出现类似于command not found的错误。如果遇到这种问题,打开编辑器的配置(可能在Shell Variables下面)设置PATH,以匹配在终端中运行echo $PATH命令时得到的输出值。你愿意的话也可以顺便设置下NODE_PATH。
1.3 &邂逅&coffee
既然你已经把编辑器设置好了,那就是时候介绍标准命令行编译器coffee了。让我们从必修的&Hello world!&程序开始。打开编辑器,创建一个名为hello.coffee的文件,添加如下内容:
直接运行它:
有几件事情你可能会感到奇怪:首先,console.log函数是从哪里冒出来的?(答案:它是一个Node.js的全局函数。)其次,JavaScript在哪里呢,不是说CoffeeScript会编译为JavaScript吗?
事实上coffee会将hello.coffee隐式地编译为JavaScript,然后将输出结果直接传递给Node,以使其立即执行。如果这不能满足你的需求,可以使用coffee众多选项中的一个或多个,使用coffee -h命令可以查看这些选项:
如果想查看刚才编译器隐藏的JavaScript,可以运行:
可以查看1.3.1节&包裹中的JavaScript&专题对多余两行代码的解释。
1.3.1 编译为JavaScript
-c(编译)可能是最常用的参数,它可以把输出的JavaScript保存到文件中。除了使用.js扩展名代替.coffee之外,新文件的文件名与原始文件的相同。让我们继续使用咖啡因饮料的主题:
编译输出到相同路径下的一个名为mochaccino.js的文件中。使用-o(输出)参数并让目标目录名称紧跟其后,就可以把输出保存在其他地方:
该示例读取source目录(包含其子目录)下的所有.coffee并把对应的.js文件写入output。注意-co是-c-o的缩写。其顺序很重要:输出目录名必须紧接在-o之后。
另外一个比较常用的参数是-w(监听),它可以让coffee命令在后台持续运行。结合-c,它在每次开发者作出改变之后重新编译代码。它甚至能在多目录下工作且能保持嵌套的目录文件结构不变。因此,如果运行下面的命令, coffee目录下的所有文件都会不断地被重新编译到js目录中:
它会持续运行直到使用
来终止编译器。
包裹中的JavaScript
你可能想知道为什么CoffeeScript编译后的代码会被包裹在一个函数内?原因用一个词来说就是命名空间。如果将一堆JavaScript文件上载到一个浏览器程序中,它们会被当做一个大的代码块,这容易产生不可预料的结果:
写第一个文件的人,对代码可能造成的破坏一无所知!为避免发生灾难可以把每个文件用一个匿名函数包裹起来,这样就隔开了两个declareNuclearWar声明(参见2.2节),这种方式叫做模块模式。
为了让模块之间可以互相通信,必须&输出&一些变量(我们会在4.1节详细介绍)。
如果一定要除去包裹函数,使用-b(暴露)参数来运行coffee命令即可。
1.3.2 REPL
不带任何参数直接运行coffee会进入编程老手所说的REPL,即Read-Eval-Print Loop。通俗地说,就是你输入点什么,它执行,然后你查看输出结果,周而复始。
这很适合用来小试一下这门语言。REPL运行在Node.js环境中,并且它会输出所有表达式的结果。例如,如果我们想回忆一下JavaScript中parseInt的某些怪异行为,可以这样试试:
coffee相关的内容就介绍到这里。再顺便说一句,如果想了解coffee是如何工作的,可以查看带注释的源码。如果你愿意,甚至可以对其进行反向工程,编写自己的CoffeeScript编译器接口(就像笔者写的Jitter 一样)。
不要忘了coffee只是一个轻量级的工具,它并不提供代码压缩或者编译后自动运行测试之类的功能。如果想把这些功能添加到自己的项目中,你就应该编写自己的生成脚本,通常就是所谓的Cakefile。你可以在CoffeeScript wiki 上找到一些Cakefile相关的文档。
几乎可以编写CoffeeScript代码了&&但还有一个问题,如果遇到错误该怎么办呢?
1.4 调试CoffeeScript
很多使用类似CoffeeScript这类语言编写代码的人都会遇到以下问题,即运行时错误参考的是编译后的代码而不是原始代码。这确实是个问题,而且大家也探讨过几个解决方案。可不幸的是,目前留给你的只有那些行号与原始代码没有任何关系的栈跟踪信息。
幸好,CoffeeScript编译后的JavaScript有很强的可读性。如果你了解这两种语言之间的对应关系(我希望读完本书后你能做到这一点),那么在原始CoffeeScript代码中找到与程序中出错的地方相匹配的位置就非常容易了。
虽然不甚理想,但这就是站在技术最前沿所要付出的代价。随着CoffeeScript生态圈的日渐成熟,工具越变越好,追踪错误将会越来越容易。Mozilla基金会的那些家伙为了给Firefox添加CoffeeScript调试支持正在拼命工作。Node也不会落后太远。但在此之前,还是彻底测试你的代码,使用调试模式日志,搞懂你的JavaScript代码吧。
有中间选择么?有的,在装配了开发控制台(或者像之前提到的Firebug Lite之类的书签工具)的Node.js或者浏览器中,可以使用console.log来显示消息。这可能会有两个问题:一是你并不想要输出每个细节,二是如果console.log不存在的话你就不会调用它。通常的解决方案就是使用包装函数,但是这样的话,当输出内容时就无法获得关键的JavaScript代码行号(因为所有的日志都是从同一个地方,即包装函数里输出的)。因此我推荐如下方式:
在这个例子中,当且仅当地址栏的&哈希&中包含字符串debug(比如page.html#debug),并且浏览器中存在console对象时,debugMode才为true。这为你提供了一种非常容易的方法,确保在页面加载时能够开启或关闭输出所有额外的信息。将debugMode声明为window的属性可以让其成为全局变量。
一种更简单但没有那么通用的方式是使用吸收操作符(详见3.1.4节)以保证当console存在时才调用console.log:
在Node下,有大量的类库(可以使用谷歌快速搜索node logging library)能够显示不同冗余度的输出。我的styout 也包含其中,它还提供对控制台色差输出的支持。
日志信息可以代替注释,在开发过程中它提供了更多关于代码如何运行的信息。比如,下面是一段典型的注释完好的代码:
可以像下面这样,调用console.log来代替注释:
另外一种习惯是在代码中使用断言,标准的console对象中有一个assert函数对此提供很好的支持,它接受一个值和错误信息作为参数(值为非真时显示错误信息)。
最后,编写结构良好的代码是避免错误的最重要的保证。尽管现在还不存在任何工具可以指出导致运行时错误的确切代码行号,但至少应该能够查到程序中可能引发错误的那部分代码。
本章中我们学习了如何使用Node.js和npm在你的机器上安装CoffeeScript。你还使用自己最爱的编辑器与这门语言来了次亲密接触,探究了使用CoffeeScript作为开发流程一部分的一些方法,并且认识到了调试工作的挑战性。
既然现在你已经知道了如何运行CoffeeScript代码,是时候深入了解该语言自身的具体细节了。本书的剩余部分会有大量小代码段,跟上思路的最好方法就是在编辑器中运行这些代码。如果搞不清楚它们是如何工作的,尝试修改一两行代码看看会发生什么。你也可以时不时地看一下编译后的JavaScript代码。
想要运行下面这种涉及某个文件的代码段,还需要额外的代码段才行:
GettingStarted/outOfContext.coffee
那些并不涉及某个文件的代码段则能独立运行:
请相信我,如果你的编辑器配置了运行命令的话将更加有趣,只需轻轻敲击快捷键就能查看代码运行结果了。这是CoffeeScript初学者的最好伙伴!
&学习CoffeeScript有助于读者成为更优秀的JavaScript开发人员。而且,本书读来酣畅淋漓,对于准备学习CoffeeScript的新手,这种体会尤为深刻。&
&&Brendan Eich,JavaScript之父
&很难想象现如今会有哪个Web程序没有大量使用JavaScript。如果你用惯了Ruby之类的语言,再使用JavaScript就会明显感觉在退步,这可不是什么愉快的事儿。来看看CoffeeScript吧:它是一个JavaScript预编译器,移除了JavaScript中不必要的冗余,让代码编写和源码阅读变成一件乐事。来,向着Coffee前进吧!这是一本很棒的CoffeeScript入门书。&
&&David Heinemeier Hansson,Ruby on Rails之父
&CoffeeScript是编程语言领域最有意思的进展之一,它吸纳Ruby和Python等语言之精华,是一个极富表现力的语言。本书将指引你进入CoffeeScript的世界;对于那些有志于提高JavaScript开发效率的开发者,本书同样必不可少!&
&&Travis Swicegood,《版本控制之道&&使用Git》作者
正在加载中,请稍候...
正在加载中,请稍候...
正在加载中,请稍候...
正在加载中,请稍候...
正在加载中,请稍候...
正在加载中,请稍候...
正在加载中,请稍候...
七日畅销榜
新书热卖榜}

我要回帖

更多关于 coffeescript css 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信