Статьи

Почему я наконец-то переключаюсь на CoffeeScript

Неправильные представления CoffeeScript

 

Возможно, вы уже слышали о CoffeeScript и некоторой ажиотаже вокруг него, но вы все же нашли несколько причин, чтобы не переключаться.
Этот пост для вас. Вот некоторые из причин, по которым я так долго держался:
  • Я хотел понять Javascript и просто не видел, как использование «более простой версии» (мои собственные мысли) облегчит мою жизнь в долгосрочной перспективе.
  • Если я использовал промежуточный язык, я хотел иметь возможность сбросить его в любое время и не чувствовать, что я вынужден продолжать использовать его.
  • Помещать еще одну вещь с ошибками между мной и моим кодом казалось глупым хардом.

Вот причины, по которым я наконец-то переключился:
  • Это менее многословный Javascript, а не другой или упрощенный язык.
  • Пара горячих клавиш, которые позволяют вам использовать списочные выражения, а не подверженные ошибкам для операторов.
  • CoffeeScript компилируется в довольно потрясающий Javascript. Из-за этого у меня не было бы никакого беспокойства в случае сброса CoffeeScript. Это также поместило бы некоторые большие соглашения в мой Javascript, которому я мог бы следовать.
  • Эли Томпсон всегда прав. (Вы должны прочитать его блог. Он умен:  http://eli.eliandlyndi.com/ )

 For-Loop Плита котла изгнана


Вот пример нескольких циклов for JavaScript, встроенных в оператор switch:
    document.onkeydown = function(event) {
      var game_piece, _i, _j, _k, _l, _len, _len2, _len3, _len4, _len5, _len6, _m, _n;
      switch (event.keyCode) {
        case 37:
          for (_i = 0, _len = game_pieces.length; _i < _len; _i++) {
            game_piece = game_pieces[_i];
            game_piece.pan_left();
          }
          break;
        case 38:
          for (_j = 0, _len2 = game_pieces.length; _j < _len2; _j++) {
            game_piece = game_pieces[_j];
            game_piece.pan_up();
          }
          break;
        case 39:
          for (_k = 0, _len3 = game_pieces.length; _k < _len3; _k++) {
            game_piece = game_pieces[_k];
            game_piece.pan_right();
          }
          break;
        case 40:
          for (_l = 0, _len4 = game_pieces.length; _l < _len4; _l++) {
            game_piece = game_pieces[_l];
            game_piece.pan_down();
          }
          break;
        case 189:
          for (_m = 0, _len5 = game_pieces.length; _m < _len5; _m++) {
            game_piece = game_pieces[_m];
            game_piece.zoom_out();
          }
          break;
        case 187:
          for (_n = 0, _len6 = game_pieces.length; _n < _len6; _n++) {
            game_piece = game_pieces[_n];
            game_piece.zoom_in();
          }
      }
      return the_screen.refresh(game_pieces);
    };

Угловатый!
Теперь, очевидно, мы могли бы немного очистить этот код … но серьезно … 

 


Хорошо, давайте просто посмотрим тот же код в CoffeeScript и насколько лучше он может быть:
  document.onkeydown = (event)->
    switch event.keyCode
      when 37 then game_piece.pan_left() for game_piece in game_pieces
      when 38 then game_piece.pan_up() for game_piece in game_pieces
      when 39 then game_piece.pan_right() for game_piece in game_pieces
      when 40 then game_piece.pan_down() for game_piece in game_pieces
      when 189 then game_piece.zoom_out() for game_piece in game_pieces
      when 187 then game_piece.zoom_in() for game_piece in game_pieces
    the_screen.refresh(game_pieces)

Это сила выражений.

Менее сложный ОО


Теперь как насчет классов?
Это проклятие программистов на Javascript везде. Есть несколько правильных способов сделать это и миллиард неправильных способов. Классы CoffeeScript — это самое большое упрощение, которое CoffeeScript вносит в Javascript, и послужило серьезной причиной моего долгого продления. Правда, это всего лишь короткая рука, которая удаляет кучу котельной плиты, так что у меня меньше возможностей вносить ошибки. Вот простой пример:
 

Простой класс Javascript:
  var foo = (function() {
    function foo(param1, param2) {
      alert("I've been constructed!");
    }
    foo.prototype.bar = function() {
      return it.shake_like(a_polaroid_picture);
    };
    return foo;
  })();

Тот же класс в CoffeeScript:
class foo
  constructor: (param1, param2)->
    alert "I've been constructed!"
  bar: ->
    it.shake_like(a_polaroid_picture)

Сойди с моей лужайки


В прошлом люди пытались компилировать в Javascript просто потому, что не получили его.
Это другое. Прошло уже более десяти лет с тех пор, как Javascript начал широко использоваться, и многие из нас получают его сейчас, когда мы начинаем видеть инструменты, которые не пытаются скрыть его за то, что он является испорченным языком. Вместо этого мы видим улучшения, внесенные в язык программирования, который мы любим и думаем, что он может быть еще лучше. Единственная причина, по которой я остаюсь придерживаться простого старого Javascript, — это ностальгия и страх перемен.

Я оставлю вас с последним примером.
Это полный набор CoffeeScript, который выполняет перетаскивание и масштабирование / панорамирование на холсте. Вы можете решить для себя, над какой версией кода вы бы предпочли работать.

До CoffeeScript:
  hand = (function() {
    function hand() {
      this.held_item = null;
    }
    hand.prototype.interact_at = function(x, y) {
      if (this.held_item !== null) {
        return this.drop_tile_if_over_it(x, y);
      } else {
        return this.pick_up_tile_if_over_it(x, y);
      }
    };
    hand.prototype.move_to = function(x, y) {
      if (this.held_item !== null) {
        return this.held_item.drag_to(x, y);
      }
    };
    hand.prototype.can_interact_with = function(touchable_game_pieces) {
      return this.game_pieces = touchable_game_pieces;
    };
    hand.prototype.drop_tile_if_over_it = function(x, y) {
      var game_piece, _i, _len, _ref, _results;
      _ref = this.game_pieces;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        game_piece = _ref[_i];
        if (game_piece.is_at(x, y)) {
          this.held_item = null;
          break;
        }
      }
      return _results;
    };
    hand.prototype.pick_up_tile_if_over_it = function(x, y) {
      var game_piece, _i, _len, _ref, _results;
      _ref = this.game_pieces;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        game_piece = _ref[_i];
        if (game_piece.is_at(x, y)) {
          this.held_item = game_piece;
          this.held_item.start_dragging(x, y);
          break;
        }
      }
      return _results;
    };
    return hand;
  })();

После CoffeeScript:
class hand
  constructor: ->
    @held_item = null
  interact_at: (x,y)->
    if @held_item != null
      @drop_tile_if_over_it(x, y)
    else
      @pick_up_tile_if_over_it(x, y)
  move_to: (x,y)->
    if @held_item != null
      @held_item.drag_to(x, y)
  can_interact_with: (touchable_game_pieces)->
    @game_pieces = touchable_game_pieces
  drop_tile_if_over_it: (x,y)->
    for game_piece in @game_pieces
      if game_piece.is_at x, y
        @held_item = null
        break;
  pick_up_tile_if_over_it: (x,y)->
    for game_piece in @game_pieces
      if game_piece.is_at x, y
        @held_item = game_piece
        @held_item.start_dragging x, y
        break;