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

    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'я каждый выберет по вкусу, это задача не в этой теме.

    Спасибо за внимание.
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 56

      +3
      Исправьте первый линк, пожалуйста. А так, спасибо большое.
        0
        исправил линки
        +2
        estupende!

        только в сасаохамлообзазных штуках бывают с отладкой проблемы. Мол ошибка в строке 795 пойди её потом в 100 строчном кофейном исходнике найди.
          +3
          ну на то и написано на сайте:
          Disclaimer: Coffeescript is just for fun. Until it reaches 1.0, there are no guarantees that the syntax won't change between versions.
        +1
        то что он компилится в нативный код это очень круто (сделали бы такой компайлер для jQuery, эх...)
        но какой-то у него синтаксис… странный…
        ну, если я не ошибаюсь, он на рубиновский похож, так что не-рубинщикам будет трудно привыкнуть…
          +3
          я долго сопротивлялся Ruby синтаксису, мне и js'ный вполне нравится, но когда кода много, то глаза начинают проситься домой, так что пришлось переосилить, уверен не зря
            0
            я как-то юзал компилятор который код {a_b_c: a+b+c } разворачивал в function( a, b ,c ){ return a+b+c } но потом забил, ибо оно того не стоит х)
                0
                хм… а чем его запускать? О_о
            +1
            Спасибо за статью.

            Несмотря на то, что вы написали, что деплой — по вкусу, стоит, наверное, упомянуть, что серверный транслятор coffee-script для своей работы требует node.js (который, кажется, сложно поставить на винду), а клиентский компилятор работает только с inline-скриптами. Ну, многие же разрабатывают в винде ведь.
              0
              ну они это, дальше писать свои сопли из джав-скрипта и кричать jQuery — круче всех
                0
                да. с win проблемы. что касается разработки, то на работе стоит windows. ставить и настраивать ubuntu можно, но не приветствуется со стороны начальства, так как на работе главное выполнить поставленные задачи.

                а по теме… народ то на винде деплоит, но ведь окончательный вариант все равно будет на сервере. если нужно использовать технологию, то и на машине нужно организовать максимально приближенную к реальности среду. для этого и денверы всякие были придуманы — с одной стороны — упростить настройку, с другой стороны предоставить почти такой же сервер, как и на хостинге (за исключением неимения прав доступа в винде). Так что это не первоочередная проблема.
                  –2
                  > народ то на винде деплоит, но ведь окончательный вариант все равно будет на сервере
                  Вы в курсе что такое win server, iis? :)
                  0
                  А почему я написал серверный транслятор, но клиентский компилятор, одному Богу известно :-)
                    0
                    почему проблема? node.js собрали под CygWin
                      0
                      Ну все отностительно. Кому и CygWin — запредельно по сравнению с Denwer :)
                      0
                      Проблема не только под win, хотел собрать под FreeBSD 8.2 amd64 из портов. Не тут то было, выкидывает что сборка не поддерживается.
                      0
                      А Я вот мечтаю о yield (во всех реализациях javascript).
                        +1
                        что-то непонятно, зачем изучать еще один язык, если и так JS знаешь?
                          0
                          >Целью и предназначением этого языка является устранение головной боли разработчика, использующего Javascript…
                            0
                            Я использую Javascript, у меня нет головной боли.
                            +2
                            чтобы «писать меньше и делать больше» %-)
                            +2
                            a = [];for (var i = 0; ( 0 <= 9? i <= 9: i >= 9); ( 0 <= 9? i += 1: i -= 1)) a.push(i);

                            магии много в этом языке я чувствую х)))
                              0
                              видимо можно писать не только 0..9 но и 9..0, кодогенерация, она такая
                                0
                                ага, и на каждой итерации проверять а не стала ли девятка ВНЕЗАПНО меньше нуля х))
                                  +1
                                  очевидная причина этого — переменная граница
                                  [1..func(systime)]
                                    –1
                                    не выдумывай х)
                              +9
                              удачи тебе с отладкой, юный фанат «быстрого» языка х)))
                                0
                                отладку прикрутят.
                                например такую же как в haxe: в дебаг версии ведется свой «стек» вызовов с привязкой к позиции в исходном файле.
                                  0
                                  ага, и пошаговую отладку прикрутят?
                                    0
                                    для пошаговой отладки достаточно готовых js-решений.
                                    но в перспективе почему бы и нет.
                                      0
                                      не достаточно, ибо в генерированном коде чёрт ногу сломит
                                        0
                                        это вам с непривички так кажется.
                                0
                                Вопрос: для JS есть куча инструментария, например jslint. Есть ли что-то подобное для Coffeescript, или в больших проектах надо опечатки искать самостоятельно?
                                  0
                                  На офсайте написано, что «it compiles into clean Javascript (the good parts)… and passes through JSLint without warnings». Как я понимаю, jslint вызывается каждый раз при компиляции в js.
                                    0
                                    Ну после компиляции в JS вызывать jslint уже смысла нет. jslint (точнее его аналог для Coffeescript) нужен для анализа исходных текстов, а не откомпилированной версии. Интересно, какие ошибки ловит Coffeescript при компиляции?
                                  0
                                  Очень интересно, спасибо за статью.,
                                  ИМХО грамотно использовать нативный синтаксис
                                    0
                                    все не могу понять эту страсть к кофе/хамл/сас. зачем учить новые синтаксисы и преумножать сущности? особенно в двух последних, которые по идее забота дизайнера/верстальщика.
                                      0
                                      Сильно утрируя: «зачем учить всякие C и Pascal, когда есть ассемблер».
                                      Вполне допускаю, что кому-то синтаксис Coffeescript будет удобнее, и что для их задач его будет достаточно.
                                      0
                                      недавно был топик с минусами этого фреймворка здесь
                                        0
                                        сократил ссылку т.к. почему-то глючит парсер ссылок

                                        здесь bit.ly/bbrkiO
                                        0
                                        Вот реально just for fun. Я не завидую JS программистам, которым через пару лет этой эйфории придется разбираться с таким кодом.
                                          0
                                          Парсер «Хабры» поломал ссылки в тексте.
                                            0
                                            Интересно приход NaCl с Python, Ruby и другими Mono спасёт любителей синтаксического сахара?
                                              –4
                                              >> Всем, кто знаком с Javascript, знают как трудно поддерживать быстро растущий код с множеством магии вроде наследования, передачи контекста объекта в callback методы и многое, многое другое.

                                              Только на одном из проектов поддерживаю ~2 MB JS-кода, поддерживать не трудно. Может язык стоит изучить, перед тем, как такое говорить?
                                                +2
                                                Да, может вы и правы, и порядка 3х лет непосредственной практики маловато для того, чтобы знать язык. Но я так не считаю. Что касается вашего комментария, то я расцениваю его как дешевый понт о том кто круче, и к данной теме он отношения не имеет. Хотите помериться крутизной — вперед, но не в этот топик
                                                  –2
                                                  Вы считаете дешёвым понтом слова о том, что на Javascript без затруднений поддерживаются крупные проекты, если выбрать нормальную архитектуру приложения? Ну ладно, считайте.
                                                    +2
                                                    я даже пояснять не стану
                                                0
                                                Привет. К как с поддержкой eclipse и др.?
                                                  0
                                                  искал плагины, для eclipse и netbeans нет (надеюсь пока нет), есть плагин для IntelliJ IDEA, для TextMate, vim и еще что то, описано тут перед списком версий, в конце страницы
                                                    0
                                                    есть неплохой плагин подсветки для gedit тут, ну и элементарный фолдинг (this, return, имена переменных)
                                                    0
                                                    Не дай бог придется поддерживать это в каком-либо проекте.
                                                      +1
                                                      Мне язык ОЧЕНЬ напоминает синтаксисом Erlang ;-) не знаю, как там с Руби (не в теме), но на эрланг похоже :)

                                                      Only users with full accounts can post comments. Log in, please.