Неправильные представления 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;