Pull to refresh

Coffeescript. И снова о нём. Резюме о приятностях

Reading time4 min
Views5.6K
CoffeeScript — это, если так можно выразиться, язык высокого уровня, преобразуемый в JavaScript.

Основан простым парнем по имени Jeremy Ashkenas при поддержке его корешей, которые упомянуты на github'е. Вдохновленный Ruby, паренёк решил упростить всем нам жизнь и создал его! CoffeeScript!



Цели



Целью и предназначением этого языка является устранение головной боли разработчика, использующего JavaScript. Всем, кто знаком с JavaScript, знают как трудно поддерживать быстро растущий код с множеством магии вроде наследования, передачи контекста объекта в callback методы и многое, многое другое. И те, у кого хватило нервов написать многостраничный native код с разбиением на классы, использующие естественное для JavaScript прототипированное наследование, могут с радостью застрелиться, так как то что они делали — это забивали гвозди тухлой рыбой :). Эй, чуваки, в CoffeeScript это делается легко и просто:

  1. class Animal
  2.   name: "animal"
  3.  
  4.   move: (meters) ->
  5.     alert(@name + " moved " + meters + "m.")
  6.  
  7. class Snake extends Animal
  8.   constructor: (name) ->
  9.     @name: name
  10.  
  11.   move: ->
  12.     alert("Slithering...")
  13.     super(5)
  14.  
  15. class Horse extends Animal
  16.   constructor: (name) ->
  17.     @name: name
  18.  
  19.   move: ->
  20.     alert("Galloping...")
  21.     super(45)
  22.  
  23. sam: new Snake("Sammy the Python")
  24. tom: new Horse("Tommy the Palomino")
  25.  
  26. sam.move()
  27. tom.move()


Мы даже можем не волноваться (до момента, когда надо будет что-то подебажить) о том какой CoffeeScript подписал контракт с всенижним, а всего лишь быть уверенными, что на выходе получим native'ный быстроработающий код:

  1. (function(){
  2.   var Animal, Horse, Snake, sam, tom;
  3.   var __extends = function(child, parent) {
  4.     var ctor = function(){ };
  5.     ctor.prototype = parent.prototype;
  6.     child.__superClass__ = parent.prototype;
  7.     child.prototype = new ctor();
  8.     child.prototype.constructor = child;
  9.   };
  10.   Animal = function() {};
  11.   Animal.prototype.move = function(meters) {
  12.     return alert(this.name + " moved " + meters + "m.");
  13.   };
  14.  
  15.   Snake = function(name) {
  16.     this.name = name;
  17.     return this;
  18.   };
  19.   __extends(Snake, Animal);
  20.   Snake.prototype.move = function() {
  21.     alert("Slithering...");
  22.     return Snake.__superClass__.move.call(this, 5);
  23.   };
  24.  
  25.   Horse = function(name) {
  26.     this.name = name;
  27.     return this;
  28.   };
  29.   __extends(Horse, Animal);
  30.   Horse.prototype.move = function() {
  31.     alert("Galloping...");
  32.     return Horse.__superClass__.move.call(this, 45);
  33.   };
  34.  
  35.   sam = new Snake("Sammy the Python");
  36.   tom = new Horse("Tommy the Palomino");
  37.   sam.move();
  38.   tom.move();
  39. })();


И не надо волноваться о конфликтах имен, так как все выполняется в своем окружении. Но если потребуется «расшарить» класс или переменную из такого «пакета», ничего же не стоит присвоить ссылку на них переменной в глобальном пространстве имен.

О документации.



Почитать на английском о том, как пользоваться CoffeeScript можно тут. На мой взгляд все доступно описано и с примерами.

Особенности.



Все coffee скрипты «варятся» в своей кофеварке, чтобы не «портить» другие coffee скрипты. Лично я считаю это правильным.

Короткая лямбда — это просто супер. А еще, что очень понравилось, так это передача контекста в callback обработчики:

  1. class Data
  2.   manyData: null
  3.  
  4.   constructor: ->
  5.     deferred: new Deferred()
  6.  
  7.     @initData(deferred)
  8.  
  9.     SomeClass.fillData(deferred)
  10.  
  11.   initData: (deferred) ->
  12.  
  13.       deferred.addCallback: (data) =>
  14.         @manyData: data
  15.  
  16.       deferred.addCallback: (error) ->
  17.         alert(error.name + ":" + error.message)
  18.  
  19. new Data()


На выходе:


  1. var Data;
  2. Data = function() {
  3.   var deferred;
  4.   deferred = new Deferred();
  5.   this.initData(deferred);
  6.   SomeClass.fillData(deferred);
  7.   return this;
  8. };
  9. Data.prototype.manyData = null;
  10. Data.prototype.initData = function(deferred) {
  11.   deferred.addCallback = (function(__this) {
  12.     var __func = function(data) {
  13.       this.manyData = data;
  14.       return this.manyData;
  15.     };
  16.     return (function() {
  17.       return __func.apply(__this, arguments);
  18.     });
  19.   })(this);
  20.   deferred.addCallback = function(error) {
  21.     return alert(error.name + ":" + error.message);
  22.   };
  23.   return deferred.addCallback;
  24. };
  25.  
  26. new Data();


Согласитесь, что код на coffee выглядит боллее адекватным.

Теперь не надо беспокоиться об объявлении переменных через var, а о слове function вообще забыть — они запрещены в CoffeeScript. Но если надо вставить обычный JavaScript в искодники CoffeeScript, просто оберните их в символы ` `:

  1. hi: `function() {
  2.   return [document.title, "Hello JavaScript"].join(": ");
  3. }`
  4.  
  5. `var getSomeValue = function() { ... }`


В результате:


  1. var hi;
  2. hi = function() {
  3.   return [document.title, "Hello JavaScript"].join(": ");
  4. };
  5. var getSomeValue = function() { ... };


Но это, думаю, может понадобиться только в крайних случаях отчаяния.

Фишки



В CoffeeScript имеется доступ к разного рода языковым конструкциям, к сожалению отсутсвующим в Native JavaScript, приведу несколько примеров, взятых с сайта проекта.

CoffeeScript


  1. cholesterol: 127
  2.  
  3. healthy: 200 > cholesterol > 60


JavaScript


  1. var cholesterol, healthy;
  2. cholesterol = 127;
  3. healthy = (200 > cholesterol) && (cholesterol > 60);


CoffeeScript


  1. theBait: 1000
  2. theSwitch:  0
  3.  
  4. [theBait, theSwitch]: [theSwitch, theBait]


JavaScript


  1. var _a, theBait, theSwitch;
  2. theBait = 1000;
  3. theSwitch =  0;
  4. _a = [theSwitch, theBait];
  5. theBait = _a[ 0];
  6. theSwitch = _a[1];


CoffeeScript


  1. numbers: [ 0 .. 9]
  2.  
  3. threeToSix: numbers[3..6]
  4.  
  5. copy: numbers[ 0...numbers.length]


JavaScript


  1. var copy, numbers, threeToSix;
  2. numbers = (function(){
  3.   a = [];for (var i =  0; ( 0 <= 9 ? i <= 9 : i >= 9); ( 0 <= 9 ? i += 1 : i -= 1)) a.push(i);
  4.   return a;
  5. }).call(this);
  6. threeToSix = numbers.slice(3, 6 + 1);
  7. copy = numbers.slice( 0, numbers.length);


CoffeeScript


  1. yearsOld: {max: 10, ida: 9, tim: 11}
  2.  
  3. ages: for child, age of yearsOld
  4.   child + " is " + age


JavaScript


  1. var _a, _b, age, ages, child, yearsOld;
  2. var __hasProp = Object.prototype.hasOwnProperty;
  3. yearsOld = {
  4.   max: 10,
  5.   ida: 9,
  6.   tim: 11
  7. };
  8. ages = (function() {
  9.   _a = []; _b = yearsOld;
  10.   for (child in _b) { if (__hasProp.call(_b, child)) {
  11.     age = _b[child];
  12.     _a.push(child + " is " + age);
  13.   }}
  14.   return _a;
  15. })();


CoffeeScript


  1. years: [2000 .. 2010]
  2.  
  3. for year in years
  4.   "year is " + year


JavaScript


  1. var _a, _b, _c, year, years;
  2. years = (function(){
  3.   a = [];for (var i = 2000; (2000 <= 2010 ? i <= 2010 : i >= 2010); (2000 <= 2010 ? i += 1 : i -= 1)) a.push(i);
  4.   return a;
  5. }).call(this);
  6. _b = years;
  7. for (_a =  0, _c = _b.length; _a < _c; _a++) {
  8.   year = _b[_a];
  9.   "year is " + year;
  10. }


Резюме



Для полноценной разработки, конечно, не хватает распространных плагинов подсветки и автодополнений, но если не учитывать этих временных трудностей, CoffeeScript по сути явно упрощает написание сложных JavaScript приложений.

Огромный плюс CoffeeScript — это то, что мы имеем возможность писать легко сложный код, который в runtime не требует подключения различных библиотек эмулирующих классические классы и те или иные реализации ecma стандартов, что каждый сможет согласится, значительно увеличит скорость работы скриптов.

А организацию режима разработки и deploy'я каждый выберет по вкусу, это задача не в этой теме.

Спасибо за внимание.
Tags:
Hubs:
+24
Comments56

Articles