首页 web前端 js教程 使用CoffeeScrip优美方式编写javascript代码_javascript技巧

使用CoffeeScrip优美方式编写javascript代码_javascript技巧

May 16, 2016 pm 03:34 PM

JavaScript无疑是在web最伟大的发明之一,几乎一切网页动态效果都是基于它丰富的计算能力。而且它的能力在各种新的JavaScript的Engine下也越来越强了,比如Google Chrome用的V8 Engine。

但是由于诞生的太早,有很多语法定义在今天看来有些效率低下了,一些更加先进的语法形式,由于历史原因,没办法加入到现在的JavaScript语言中,可以说一种遗憾。

世界上的很多天才都在为构建更好的JavaScript而努力。已经有了很多尝试,其中最有前途的,无非就是CoffeeScript和TypeScript了。面对CoffeeScript,我有一见如故的感觉;而TypeScript也激发了我极大的兴趣。CoffeeScript和TypeScript一样,都是编译为JavaScript的语言,它们都增强了JavaScript的表达能力。这篇文章是讲CoffeeScript的,TypeScript将放在下一篇再讲。

所谓编译为JavaScript,是指CoffeeScript和TypeScript没有实现自己的运行时,它们都是编译为等价的JavaScript代码,然后放在JavaScript的解释器上运行。

CoffeeScript

简洁性

CoffeeScript给人最大的印象就是其简洁的表达。下面代码是我从CoffeeScript中文摘抄下来的:

# 赋值:
number  = 42
opposite = true
# 条件:
number = -42 if opposite
# 函数:
square = (x) -> x * x
# 数组:
list = [1, 2, 3, 4, 5]
# 对象:
math =
 root:  Math.sqrt
 square: square
 cube:  (x) -> x * square x
# Splats:
race = (winner, runners...) ->
 print winner, runners
# 存在性:
alert "I knew it!" if elvis?
# 数组 推导(comprehensions):
cubes = (math.cube num for num in list)

登录后复制

上面的代码会编译为等价的JavaScript代码:

var cubes, list, math, num, number, opposite, race, square,
 __slice = [].slice;
number = 42;
opposite = true;
if (opposite) {
 number = -42;
}
square = function(x) {
 return x * x;
};
list = [1, 2, 3, 4, 5];
math = {
 root: Math.sqrt,
 square: square,
 cube: function(x) {
  return x * square(x);
 }
};
race = function() {
 var runners, winner;
 winner = arguments[0], runners = 2 <= arguments.length &#63; __slice.call(arguments, 1) : [];
 return print(winner, runners);
};
if (typeof elvis !== "undefined" && elvis !== null) {
 alert("I knew it!");
}
cubes = (function() {
 var _i, _len, _results;
 _results = [];
 for (_i = 0, _len = list.length; _i < _len; _i++) {
  num = list[_i];
  _results.push(math.cube(num));
 }
 return _results;
})();
run: cubes
登录后复制

CoffeeScript力求简洁。其简洁性首先表现在对一些仅用于语法控制的符号进行了去除。这其中包括:

取消分号

取消var声明

取消大括号包围内层代码,使用缩进取代

函数调用在没有歧义的情况下可以省略括号

var声明涉及到复杂又很鸡肋的JavaScript变量作用域机制。这部分内容先放着不讲。CoffeeScript通过完全取消var声明机制而使得问题得到简化。总之,在CoffeeScript世界里,变量不用事先声明,直接用就是了。而且这种用法基本没有什么危险。

缩进在CoffeeScript中不仅仅在于美化代码,其代表了代码层次的组织,是有特别的含义的。简单地说就是,不适用大括号包围内层代码,而是内层代码要缩进。不同的缩进代表了不同的代码层次。形式和内容是一致的。

缩进的例子:

#if缩进
if true
 'true'
else
 'false'
#while缩进
while true
 'true'
#函数缩进
(n) ->
 n * n
#对象字面量缩进
kids =
 brother:
  name: "Max"
  age: 11
 sister:
  name: "Ida"
  age: 9 
登录后复制

在不引起歧义的情况下,CoffeeScript的函数调用可以省略括号。例如console.log(object)可以简化为console.log object。所谓引起歧义的一个例子就是无参数的情况下,console.log就不知道是取出函数型属性log还是调用函数log了。

CoffeeScript的函数表达式也做了极致的精简精简。一个单行函数的定义可以这样:

square = (x) -> x * x
登录后复制

而多行函数也是通过缩进来组织的。一个空的函数最为简洁,是这样:->。

函数的这种简洁表达使得传递回调函数非常便利。一个数组的map可能像这样就足够了:

list = [1, 2, 3]
list.map (e) -> e+1
登录后复制

而等效的JavaScript代码就不能这么马虎:

list = [1, 2, 3];
list.map(function(e) { return e + 1; });
登录后复制

增强的表达

CoffeeScript提供了JavaScript所没有的一些强大的表达语法,这也是被称为语法糖的东西。在我印象中,这种增强性是很多的,我举出两个有代表性的例子:

字符串插值法

列表解析

其中字符串插值法是对现有字符串能力的一种扩充和语法上的简化;而列表解析就要涉及到观念上的改变了。前者是一种改良,后者则是一种变革。

字符串插值法

在CoffeeScript的字符串里,可以用#{…}嵌入一个表达式。例如:

"#{ 22 / 7 } is a decent approximation of π"

等价于:

"" + (22 / 7) + " is a decent approximation of π";

插值在这里起到占位的作用,使得动态内容的字符串更容易构建。我想人人都能接受这样的表达。

列表解析

列表解析是CoffeeScript的世界里的重要一员。它改变了循环的思路。CoffeeScript没有提供像JavaScript那样的for循环结构,而是统统转化为列表解析。一个常规的JavaScript for循环,像下面这样:

food_list = ['toast', 'cheese', 'wine'];
for (i = 0, len = food_list.length; i < len; i++) {
 food = food_list[i];
 eat(food);
}
登录后复制

用CoffeeScript实现就是:

food_list = ['toast', 'cheese', 'wine']
eat food for food in food_list #做个小补充,for循环的单条语句的写法

单单是上面的例子不足以显示列表解析的强大(却看到它的简洁了)。在继续这个话题之前,我觉得我有必要补充一下另一个涉及到CoffeeScript理念的东西了:一切皆是表达式。

在CoffeeScript世界里,一切语句都是表达式语句,都会返回一个值。函数调用默认会返回最后一条语句的值。if条件结构也会返回值,其返回的是执行的最后一条语句的值。循环结构有些不同,其会将每次循环的结果都保存在一个数组里,作为此循环结构的值。例如下面代码的list结果就是[5, 4, 3, 2, 1]。

num = 6
list = while num -= 1
 num
登录后复制

回到列表解析的主题。与while一样,for结构也是一种循环的表达,其结果也是一个数组。回到先前的例子,下面的小代码的list结果就是['t', 'c', 'w']。

food_list = ['toast', 'cheese', 'wine']
list = (food[0] for food in food_list)
登录后复制

我们已经看到for循环的each形式

eat food for food in food_list
登录后复制

以及它的map形式

(food[0] for food in food_list)
登录后复制

下面给出它的filter形式

(food for food in food_list when food is 'wine')
登录后复制

列表解析的特色的地方在于它改变了我们组织循环的方式和解析数组的模式。这是一种声明式的编程方法,告诉程序你想要什么而不去关心构建的过程。

类的支持

类是CoffeeScript对JavaScript的一个很重要的补充。JavaScript的原型功能很强大,写法上又恨别扭。正确地设置原型链以实现继承关系也是个很大的挑战。CoffeeScript从语法上直接支持类的定义,自然且隐藏细节。

class Animal
 constructor: (@name) ->
 move: (meters) ->
  alert @name + " moved #{meters}m."
class Snake extends Animal
 move: ->
  alert "Slithering..."
  super 5
class Horse extends Animal
 move: ->
  alert "Galloping..."
  super 45
sam = new Snake "Sammy the Python"
tom = new Horse "Tommy the Palomino"
sam.move()
tom.move()
登录后复制

从实现上来说,CoffeeScript的类与JavaScript的构造函数和原型链那一套并无二致。所以,理解原型机制也是理解CoffeeScript类的基础。

关于JavaScript的糟粕

CoffeeScript的另一个目标是从语法层面上直接消除JavaScript的被人诟病的一些糟粕部分。前面已经说过关于分号的部分。关于var声明的部分。分号的机制暂且不去例会,总之CoffeeScript不用再去写分号了。

在JavaScript当中,最为人诟病的糟粕部分有两处,因为它们使用的情况最多而且容易出错。

全局变量

相等比较

全局变量

JavaScript的作用域规则很复杂,涉及到var声明机制和变量提升。在JavaScript里,构造一个全局变量是很容易的,有三种方式:

在全局的环境里用var声明

var name = 'name';
登录后复制

在函数内用省略var的方式定义

function foo() {
  name = 'name';
}
登录后复制

绑定到window的属性

window.name = 'name';

其中第1种和第2种方式是最常见的错误用法。首先不推荐直接在全局环境中编码,而是应该用一个匿名函数包裹起来,将程序的作用域限制在这个匿名函数中。第二种用法完完全全就是忘记了var声明。而我在实际的JavaScript编码中,忘记var声明是常有的事(就像经常忘记行末补上分号一样)。

而在CoffeeScript里面就完全没有这种担心了。首先,编译后的JavaScript代码不会暴露在全局环境里,所有的代码都是自动包裹在一个匿名函数(function(){ ... })();内。然后,所有的变量都会自动加上var声明。这就使得不小心污染全局的情况很难发生,除非使用赋值到window上。

相等比较

我们都知道JavaScript有两种比较运算符:==和===。我们也知道==在使用的过程中会很坑,所以平时都宁愿多打一个字符而使用===。CoffeeScript的只有一种比较运算符==,而它会编译成JavaScript的===,从而很好地避过了这道坑。

是否该使用CoffeeScript

CoffeeScript简化和增强了JavaScript的表达能力,尽可能地从语法层面上就能避免JavaScript的一些坑。用它写代码,会让人有更清晰舒适的感觉,而且不容易犯错。CoffeeScript的初衷就是提供更好的JavaScript。

然而,CoffeeScript与JavaScript是不兼容的。它既不是JavaScript的子集,也不是超集,而是与JavaScript有着显然不同思路的一种语言。用CoffeeScript编程就必然要转换观念,尽管这种观念更好更自然,但却是有些固步自封的人望而却步的主要原因了。

CoffeeScript并不是适合每一个人的。有些人对于用缩进组织代码层次完全不能接受,也不能接受用箭头函数表达法。对于他们来说,去掉function关键字和大括号的组织怎么看都怎么地不顺眼。

列表解析很强大,却也显得过于简洁了。对于习惯了构造冗杂JavaScript程序的人们来说,并不习惯这种表达方式。

总之,是不可强求别人去学习使用CoffeeScript。JavaScript已经足够强大,只要足够小心,完全可以使用JavaScript很好地完成工作。对于那些想要尝试CoffeeScript,我们也要给予鼓励的态度,他们是求新求变的勇士。CoffeeScript真的值得一试,而且它真的很小巧,完全掌握它不是件困难的事。

对于在团队推行CoffeeScript,我本人更是持有保守的看法。如果团队从一开始就使用CoffeeScript还好。如果是要从CoffeeScript转为JavaScript,就要谨慎行之。一种可行的方式是先尝试在一个小项目中使用CoffeeScrip,看看效果如何。

对于个人来说,就没有什么限制了。如果真的喜欢,就去尝试吧。你可以使用CoffeeScript写脚本,构建自己的网站,做一些小玩意。

以上内容是小编给大家介绍的使用CoffeeScrip优美方式编写javascript代码,希望大家喜欢。

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在JavaScript中替换字符串字符 在JavaScript中替换字符串字符 Mar 11, 2025 am 12:07 AM

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

自定义Google搜索API设置教程 自定义Google搜索API设置教程 Mar 04, 2025 am 01:06 AM

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

8令人惊叹的jQuery页面布局插件 8令人惊叹的jQuery页面布局插件 Mar 06, 2025 am 12:48 AM

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

构建您自己的Ajax Web应用程序 构建您自己的Ajax Web应用程序 Mar 09, 2025 am 12:11 AM

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

什么是这个&#x27;在JavaScript? 什么是这个&#x27;在JavaScript? Mar 04, 2025 am 01:15 AM

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可

通过来源查看器提高您的jQuery知识 通过来源查看器提高您的jQuery知识 Mar 05, 2025 am 12:54 AM

jQuery是一个很棒的JavaScript框架。但是,与任何图书馆一样,有时有必要在引擎盖下发现发生了什么。也许是因为您正在追踪一个错误,或者只是对jQuery如何实现特定UI感到好奇

10张移动秘籍用于移动开发 10张移动秘籍用于移动开发 Mar 05, 2025 am 12:43 AM

该帖子编写了有用的作弊表,参考指南,快速食谱以及用于Android,BlackBerry和iPhone应用程序开发的代码片段。 没有开发人员应该没有他们! 触摸手势参考指南(PDF) Desig的宝贵资源

如何创建和发布自己的JavaScript库? 如何创建和发布自己的JavaScript库? Mar 18, 2025 pm 03:12 PM

文章讨论了创建,发布和维护JavaScript库,专注于计划,开发,测试,文档和促销策略。

See all articles