Статьи

Вы используете CoffeeScript?

В этом нет двух способов: индустрия веб-разработки может быть невероятно жесткой. Это тот, который требует от нас непрерывного обучения на протяжении всей нашей карьеры. Возьмите несколько лет отдыха, и внезапно вы окажетесь в погоне за новыми фреймворками, инструментами, лучшими практиками и препроцессорами. Правильно, детки, если вы хотите стать веб-разработчиком, вам лучше согласиться с идеей, что ваше обучение никогда не закончится (и вы не должны этого хотеть).

CoffeeScript.org, естественно, должен быть вашей первой остановкой при изучении CoffeeScript. Его документация просто фантастическая.

Как только мы признаем, что определенный процент каждой недели должен быть потрачен на совершенствование наших навыков и изучение новых вещей, определение того, во что, в частности, инвестировать наше время, становится невероятно важным. Казалось бы, каждый день новые библиотеки или инструменты выпускаются для публики. Но это не значит, что мы должны отбросить осторожность (и время) и обнять их всех; не за что. Конечно, имейте любопытный ум, но здоровый уровень скептицизма имеет первостепенное значение.

Однако некоторые инструменты неизбежно быстро попадают в начало «нового и блестящего» списка.

Это типы, которые могут переопределить то, как мы создаем сеть. jQuery переопределил способ, которым мы запрашиваем и работаем с DOM. Backbone.js помогает разработчикам превратить их спагетти-код в хорошо структурированные и поддерживаемые модули. И, возможно, CoffeeScript заново изменит способ, которым мы физически пишем наш JavaScript.

Есть только одна проблема: CoffeeScript не добавляет ничего нового в язык JavaScript; он просто предлагает улучшенный (многие сказали бы радикально улучшенный) синтаксис, который в конечном итоге компилируется в обычный JavaScript. Итак, наша дилемма заключается в следующем: в среде, которая уже требует от нас изучения бесчисленных языков, методов и шаблонов, действительно ли стоит потратить время на изучение еще одного препроцессора? Что ж, в то время как ответ на этот вопрос, безусловно, можно обсудить , по мнению этого автора, вам непременно стоит покопаться!


Вполне возможно, что вы впервые слышите о CoffeeScript. Если так, не волнуйтесь; это только сейчас начинает по-настоящему набирать обороты в сообществе разработчиков.

По сути, CoffeeScript, созданный Джереми Ашкенасом, превращает то, что некоторые называют «ужасным JavaScript», в чистый и лаконичный код. Он не расширяет функциональность языка JavaScript; это просто слои более красивого синтаксиса.

Лучший способ продемонстрировать то, что предлагает CoffeeScript, — прогуляться по синтаксису.

Вкладка «Попробуйте CoffeeScript» на CoffeeScript.org предлагает компиляцию в реальном времени; это отличный способ поиграть с синтаксисом.)

Если вы просто хотите поиграть с синтаксисом, посетите CoffeeScript.org и нажмите на вкладку «Попробуйте CoffeeScript». С другой стороны, если вы хотите установить CoffeeScript локально, убедитесь, что в вашей системе установлены актуальные копии Node.js и npm (Node Package Manager). Не волнуйся; это просто.

Далее CoffeeScript можно установить из командной строки:

1
npm install -g coffee-script

Это оно! Вы готовы идти. Чтобы посмотреть файл, script.coffee и скомпилировать его в script.js каждом сохранении файла, в командной строке перейдите к корню проекта и введите:

1
coffee —watch —compile script.coffee

Кроме того, многие редакторы, такие как TextMate и Sublime Text 2, предлагают пакеты, которые превращают этот процесс сборки в простое нажатие клавиши. Как альтернативный вариант, обратитесь к приложениям, таким как LiveReload и CodeKit, которые будут автоматически выполнять задачу «смотреть и компилировать».

LiveReload автоматизирует процесс просмотра и компиляции файлов CoffeeScript.)

Рассмотрим следующий фрагмент кода:

1
2
var foo = ‘bar’;
var bar = ‘baz’;

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

Приведенный выше код может быть переписан как:

1
2
foo = ‘bar’
bar = ‘baz’

Когда код в конечном итоге компилируется в обычный JavaScript, оба имени переменных будут объявлены в верхней части области функции, а затем назначены соответствующим образом, например, так:

1
2
3
4
var bar, foo;
  
foo = ‘bar’;
bar = ‘baz’;

Многие разработчики JavaScript ненавидят тот факт, что все выражения должны заканчиваться точкой с запятой.

1
var foo = ‘bar’;

Технически, вы обнаружите, что часто вы можете избежать с запятой; но, тем не менее, есть некоторые ошибки, связанные с этим подходом, и считается наилучшей практикой всегда включать их для максимальной уверенности.

В CoffeeScript, однако, мы можем помахать им навсегда. Таким образом, предыдущий фрагмент кода может быть изменен на:

1
foo = ‘bar’

Взяв дополнительные подсказки от языков, таких как Ruby, в CoffeeScript, скобки тоже часто можно опустить. Это преобразует традиционный JavaScript, такой как:

1
2
3
if ( guess === 10 ) {
  result = ‘correct’;
}

в:

1
2
if guess == 10
 result = ‘correct’

Более того, мы можем быть более краткими, используя модификатор оператора:

1
result = ‘correct’ if guess == 10

Намного чище и читабельнее, а? «Установите result на« правильный », если переменная guess равна 10.« Отлично!

Обратите внимание, что CoffeeScript компилирует все == в версию строгого равенства === , как рекомендовано такими инструментами, как JS Lint.

Вы быстро обнаружите, что в CoffeeScript один и тот же блок кода может быть переписан несколькими способами. Хотя вы можете игнорировать их, псевдонимы позволяют проводить более удобочитаемые сравнения. Следующие группировки идентичны как по функциональности, так и по компиляции.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// equality
launch == ‘go’
launch is ‘go’
  
  
// inequality
launch != ‘go’
launch isnt ‘go’
  
  
// not
return false if !goForFlight
  
return false if not goForFlight
  
return false unless goForFlight
  
  
// true
return true
return on
return yes
  
  
// false
return false
return off
return no
  
  
// and
goForFlight &&
goForFlight and launch()
  
  
// or
goForFlight ||
goForFlight or prepare()

Функции являются ключевой областью, где синтаксис значительно отличается от JavaScript. Традиционная функция, которая определяет, будет ли это день оплаты или пятница, может выглядеть следующим образом:

1
2
3
var payDay = function() {
   return new Date().getDay() === 5;
}

В попытке убрать беспорядок с помощью CoffeeScript эту функцию можно переписать так:

1
2
payDay = ->
 new Date().getDay() == 5

В качестве альтернативы, мы можем поместить весь бит кода в одну строку.

1
payDay = -> new Date().getDay() == 5

Здесь стоит отметить две ключевые вещи:

  1. function() была заменена на -> .
  2. Последняя строка функции всегда будет возвращена. Таким образом, ключевое слово return может быть удалено в данном конкретном случае.

Любые применимые аргументы должны быть заключены в круглые скобки перед -> . Возможно, день оплаты в четверг; если так, функция может быть изменена, чтобы быть более гибкой.

1
2
payDay = (day) ->
 new Date().getDay() == day

Но что, если мы хотим назначить день выплаты по умолчанию в пятницу (или 5)? В обычном JavaScript мы бы, вероятно, сделали:

1
2
3
4
var payDay = function(day) {
  day ||
  return new Date().getDay() === day;
}

С CoffeeScript, с другой стороны, мы можем значительно сократить это.

1
2
payDay = (day = 5) ->
 new Date().getDay() == day

Острота!

Типичный объект JavaScript может быть значительно очищен в CoffeeScript. Учтите следующее:

1
2
3
4
5
var person = {
   legs: 2,
   hands: 2,
   fingers: 10
}

CoffeeScript позволяет нам удалить ключевое слово var , а также фигурные скобки и запятые. Однако в одной строке запятые по-прежнему необходимы.

1
person = legs: 2, hands: 2, fingers: 10

Однако, если мы разместим каждое свойство в отдельной строке, они могут быть опущены. То же самое верно для массивов.

1
2
3
4
person =
 legs: 2
 hands: 2
 fingers: 10

Важно : поскольку CoffeeScript зависит от пробелов, даже одна строка с неверным отступом может кардинально изменить способ компиляции кода в JavaScript.

Понимание позволяет нам легко преобразовать десять строк кода в несколько. По сути, это способ создания выражений для итерации по предоставленному набору элементов в массиве или объекте.

Например, вместо использования типичного for оператора — и «кэширования», которое сопровождает итерации по массиву — мы можем вместо этого использовать for in .

Давайте представим, что нам нужно перебрать массив символов. С традиционным JavaScript мы могли бы сделать:

1
2
3
4
5
var characters = [‘Marty’, ‘Doc’, ‘Biff’];
  
for ( var i = 0, len = characters.length; i < len; i++ ) {
   console.log(«Get %s to the time machine», characters[i]);
}

Это конечно не красиво; но если мы вместо этого используем CoffeeScript, это может быть красиво.

1
2
3
characters = [‘Marty’, ‘Doc’, ‘Biff’]
for person in characters
  console.log «Get %s to the time machine», person

Разве это не здорово писать? Конечно, я не могу быть единственным!

Как вы вскоре увидите, мы можем даже использовать интерполяцию строк для дальнейшего улучшения кода, но я забегаю вперед.

Однако есть проблема: мы непреднамеренно направили Биффа к машине времени, что не очень хорошая идея. Давайте изменим код, указав, что он должен записывать строку только в консоль при условии, что текущим человеком в массиве не является Biff . В CoffeeScript, если мы воспользуемся преимуществами фильтров, это просто.

1
2
3
characters = [‘Marty’, ‘Doc’, ‘Biff’]
for person in characters when person isnt ‘Biff’
  console.log «Get %s to the time machine», person

Ага; Средство правовой защиты потребовало всего четыре читаемых человеком слова.

Теперь, если мы хотим, мы можем сделать эти циклы более читабельными, используя понимание списка. Чтобы перебрать массив characters и записать имя каждого человека на консоль:

1
console.log person for person in characters

Или, в качестве другого примера, чтобы извлечь все теги привязки со страницы (используя метод map jQuery), сохранить значение href каждого привязки в массиве и, наконец, выполнить цикл по этому массиву и записать значения в консоль, используя обычный JavaScript, мы сделал бы:

1
2
3
4
5
var links = $(‘a’).map(function() {
   return this.href;
});
  
console.log(links.join(‘, ‘));

Однако с CoffeeScript у нас есть лучший выбор:

1
console.log ( link for link in $(‘a’).map -> @href ).join ‘, ‘

В качестве последнего примера, что если бы у нас был массив объектов person:

01
02
03
04
05
06
07
08
09
10
people = [
  name: ‘Jeffrey’
  age: 27
,
  name: ‘John’
  age: 13
,
  name: ‘Jan’
  age: 42
]

Наша задача — создать новый массив с именем ofAge и сделать его равным списку только тех объектов, возраст человека которых составляет 21 год или старше. Опять же, с обычным, ванильным JavaScript, мы можем сделать:

1
2
3
4
5
6
7
var ofAge = [];
  
for ( var i = 0, len = people.length; i < len; i++ ) {
   if ( people[i].age >= 21 ) {
     ofAge.push( people[i] );
   }
}

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

1
ofAge = ( p for p in people when p.age >= 21 )

Бам! Оборачивая все, что происходит после знака равенства в скобках, мы указываем, что переменная ofAge должна быть равна результатам этой операции, которая будет массивом. Таким образом, массив будет построен, а затем назначен для ofAge . Если запутался, просто прочитайте выражение слева направо. «Выдвиньте объект person в массив results , для каждого person в массиве people … до тех пор, пока свойство age этого лица больше или равно 21.» Ключевое слово when называется фильтром и может быть невероятно мощным. Признайтесь: вы начинаете выделять слюну.

В предыдущем разделе мы использовали довольно типичный метод для привязки переменной к строке.

1
console.log «Get %person to the time machine», person

Подобно языкам, как Ruby, CoffeeScript предлагает интерполяцию строк через синтаксис #{} . Этот код можно переписать так:

1
console.log «Get #{person} to the time machine»

Обратите внимание, что, как и в большинстве языков, чтобы использовать преимущества интерполяции строк, вы должны использовать двойные кавычки, а не одинарные.

Рассмотрим довольно распространенную задачу кэширования ссылки на this , чтобы при изменении контекста — например, в рамках обратного вызова привязки события jQuery — мы все равно могли получить доступ к кэшированному местоположению. Вот пример:

1
2
3
4
5
6
7
var self = this;
  
$(‘h1’).on(‘click’, function() {
  // ‘this’ now refers to the anchor that was clicked
  // use self instead
  self.someMethod();
});

CoffeeScript предоставляет «жирную стрелку», или => , которая может оказать огромную помощь. Если мы изменим -> на => , за кулисами CoffeeScript будет кешировать ссылку на this . Затем внутри функции все ссылки на this будут динамически заменены кэшированной версией.

Чтобы проиллюстрировать эту идею, следующий код:

1
$(‘h1’).on ‘click’, => this.someMethod()

… Будет компилироваться в:

1
2
3
4
5
var _this = this;
  
$(‘h1’).on(‘click’, function() {
  return _this.someMethod();
});

CoffeeScript предоставляет полезный синтаксис class для тех, кто предпочитает более классический подход к структурированию своего кода. Например, просто набрав class Person , CoffeeScript скомпилирует этот код в:

1
2
3
4
5
6
7
8
9
var Person;
  
Person = (function() {
  
  function Person() {}
  
  return Person;
  
})();

Обратите внимание на то, что переменная Person равна самовызывающемуся выражению функции, которое возвращает внутреннюю функцию Person . Если нам нужно выполнить немного кода сразу после создания экземпляра, подобно PHP-методу __construct , мы можем поместить наш код init в метод конструктора class , например, так:

1
2
3
4
class Person
 constructor: (name, age) ->
   this.name = name
   this.age = age

Метод constructor не может быть вызван явно; вместо этого он запускается динамически, когда вы создаете экземпляр класса. Этот код может быть улучшен, однако; CoffeeScript предоставляет дополнительный сахар, который может сократить его. В CoffeeScript символ @ всегда будет ссылаться на this или на экземпляр Person . Таким образом, вместо this.age мы можем использовать @age , с которым разработчики Ruby будут знакомы. Код выше может быть переписан как:

1
2
3
4
class Person
 constructor: (name, age) ->
   @name = name
   @age = age

Еще лучше, однако, мы можем сделать еще один шаг вперед. Эти переменные экземпляра могут быть установлены по-другому:

1
2
class Person
 constructor: (@name, @age) ->

Неплохо, а? На этом этапе, чтобы расширить прототип Person дополнительными методами, мы просто создаем новые методы так же, как мы добавляем методы к объекту. За кулисами CoffeeScript присоединит метод к прототипу. Давайте добавим метод, который определяет год рождения человека.

1
2
3
4
class Person
 constructor: (@name, @age) ->
 getBirthYear: ->
   new Date().getFullYear() — @age

Этот красивый, чистый код, когда-то скомпилированный в JavaScript, будет:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
var Person;
  
Person = (function() {
  
  function Person(name, age) {
    this.name = name;
    this.age = age;
  }
  
  Person.prototype.getBirthYear = function() {
    return new Date().getFullYear() — this.age;
  };
  
  return Person;
  
})();

Итак, мы эффективно сократили количество строк с шестнадцати до четырех. Чтобы создать экземпляр этого нового класса, мы можем написать:

1
2
man = new Person(‘Jeffrey’, 27)
man.getBirthYear() # 1985

Более того, для создания дочерних классов, которые расширяют Person , нам нужно использовать только ключевое слово extends:

1
class Child extends Person

Теперь у Child есть доступ ко всем свойствам и методам из класса Person , и они могут ссылаться или перезаписывать их по своему усмотрению.


Несмотря на весь этот великолепный сахар, у нас все еще остается вопрос: должны ли мы использовать CoffeeScript в производстве? Ну, Джон В. Читатель, это в значительной степени зависит от вас. Есть веские аргументы за и против. Отрицатели укажут на тот факт, что, поскольку вы не работаете специально со скомпилированным JavaScript, отладка потенциально может стать более сложной задачей. Вы отлаживаете код, который не написал. Это может быть борьба.

«Я думаю, что CoffeeScript — блестящий эксперимент. CoffeeScript берет хорошие части, и помещает минимальный синтаксис сверху, который прекрасен. Я не рекомендую использовать его в производстве, потому что у него свой мир проблем. — Дуглас Крокфорд »

Можно также утверждать, что слишком сильная зависимость от таких абстракций может привести к тому, что разработчик будет меньше понимать JavaScript в целом. Поскольку в компилятор внедряется так много лучших практик, это облегчает разработчику задачу запоминания этих лучших практик, таких как избегание глобальных переменных и подъем переменных. Является ли этот вид автоматизации хорошей вещью, подлежит обсуждению.

«Лучшая практика, которая может быть применена и сгенерирована компилятором, лучше, чем лучшая практика, которую нужно каждый раз запоминать и печатать вручную». — Джереми Ашкенас

Чтобы сыграть адвоката дьявола, то же самое можно сказать и о jQuery. Поддерживает ли jQuery новое поколение разработчиков, которые никогда не изучают ванильный JavaScript? Точно нет; во всяком случае, это очень помогло в возрождении языка JavaScript.

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


Чтобы узнать больше мнений CoffeeScript от мастеров JavaScript — по обе стороны ограждения — обратитесь к разделу « Если вы изучите CoffeeScript » от Nettuts +. )

В конечном счете, CoffeeScript — это просто JavaScript. Он предлагает красивый синтаксис, который находится на вершине языка. Плюсы очевидны: код автоматически придерживается лучших практик, становится короче, менее подвержен ошибкам и значительно более читабелен. Но опять же, отладка, которая может занять значительное время в рабочем процессе разработчика, является проблемой.

Выбор остается за вами! Что касается твоего истинного, ну, я не могу себе представить возвращение. Я все с CoffeeScript.