Использование пробелов как разграничительных знаков(вместо скобок, точек с запятой и прочих), делает CoffeeScript кратким. По сравнению с JavaScript, строка для того же конкретного кода в CoffeeScript сокращается примерно до половины (примерно на 55 % меньше). Так же CoffeeScript позволяет избежать проблем с объявлением области действия в программе, поскольку в отличие от JavaScript использование ключевого слова var перед объявлением переменной не требуется. Помимо этого, в CoffeeScript есть ряд удобных функций, таких как осмысление массивов, псевдонимы прототипов и классы, которые ещё больше сокращают количество вводимых символов.
Дополнительный этап компиляции между написанным кодом и кодом на JavaScript увеличивает общее время компиляции программы. CoffeeScript не является широко используемым, из-за чего сложнее искать источники информации по нему и кооперировать с другими разработчиками
В CoffeeScript синтаксис для комментариев заимствован из Ruby, где каждый однострочный комментарий начинается со знака решетки#, а многострочные комментарии заключены между тремя символами решетки:
Неподдерживаемость CoffeeScript глобальных переменных предотвращает ошибки доступа, которые могли возникнуть в JavaScript при случайном объявлении глобальной переменной.
CoffeeScript удаляет довольно многословный оператор функции и заменяет его тонкой стрелкой: ->. Функции могут быть однострочными или отступать на несколько строк. Последнее выражение в функции неявно возвращается.
CoffeeScript:
func=->"bar"func=-># An extra line"bar"
#"ltr">
functionfunc(){return"bar";}// другой вариант (с использованием стрелочной функции)letfunc=()=>"bar";
Функции можно вызывать точно так же, как и в #"/w/index.php?title=CoffeeScript&veaction=edit§ion=12" title="Редактировать раздел «Объектные литералы и объявление массивов»">править |править код]
Объектные литералы задаются точно так же, как и в JavaScript, с помощью пары скобок и операторов ключ/значение. Однако, как и в случае с вызовом функций, в CoffeeScript скобки необязательны. Вместо запятых можно использовать отступы и новые строки.
CoffeeScript:
object1={one:1,two:2}# Without bracesobject2=one:1,two:2# Using new lines instead of commasobject3=one:1two:2User.create(name:"John Smith")
Если операторif расположен в одной строке, необходимо использовать ключевое слово then, чтобы CoffeeScript знал, когда начинается блок. Условные операторы (?:) не поддерживаются, вместо них следует использовать однострочный операторif/else.
CoffeeScript поддерживает интерполяцию строк (то есть вставка значения переменной в качестве текста внутрь строки): делается это посредством использования#{} внутри строки, заключённой в двойные кавычки. На момент выхода CoffeeScript у JavaScript не было такой возможности, однако с выходом стандарта ECMAScript 6 в 2015 году возможность так делать появилась и в #"/wiki/%D0%93%D1%80%D0%B0%D0%B2%D0%B8%D1%81" title="Гравис">грависа), а вставка переменных производится с использованием${}.
CoffeeScript:
favourite_color="Blue. No, yel..."question="Bridgekeeper: What... is your favourite color? Galahad:#{favourite_color} Bridgekeeper: Wrong!"
#"ltr">
letfavouriteColor="Blue. No, yel...";letquestion=`Bridgekeeper: What... is your favourite color? Galahad:${favouriteColor} Bridgekeeper: Wrong!`;
CoffeeScript черпает вдохновение из Ruby, когда речь идет о создании массивов с помощью диапазонов. Диапазоны создаются двумя числовыми значениями, первой и последней позициями в диапазоне, разделенными... Если диапазон не имеет никакого префикса, CoffeeScript расширяет его до массива.
CoffeeScript:
range=[1..5]
#"ltr">
letrange=[1,2,3,4,5];
Если же диапазон указывается сразу после переменной, то CoffeeScript преобразует его в вызов метода.slice().
Ключевое словоclass было добавлено в JavaScript в стандарте ECMAScript 6. При этом, JavaScript и до этого поддерживал классы (за счёт использования прототипов), а само ключевое словоclass является синтаксическим сахаром:
classPerson{constructor(name){this.name=name;}say(phrase){return`${this.name} говорит${phrase}`;}}// Данный код полностью эквивалентен следующему коду:functionPerson(name){this.name=name;}Person.prototype.say=function(phrase){returnthis.name+" говорит "+phrase;}
Далее для JavaScript-кода в данном разделе будет использоваться синтаксис с использованиемclass.
CoffeeScript использует собственный прототип JavaScript для создания классов, добавляя немного синтаксического сахара для наследования статических свойств и сохранения контекста. В CoffeeScript используются функции-конструкторы, что означает возможность инстанцирования классов с помощью оператора new. CoffeeScript предоставляет сокращение для общего шаблона установки свойств экземпляра класса. Префикс аргумента @ позволяет CoffeeScript автоматически устанавливать аргументы как свойства экземпляра в конструкторе.
Добавление дополнительных свойств экземпляра в класс очень просто, это точно такой же синтаксис, как и добавление свойств к объекту. Свойства должны быть правильно расположены с отступом внутри тела класса.
Статические свойства копируются в подклассы, а не наследуются по прототипу, как свойства экземпляра. Это связано с особенностями реализации прототипической архитектуры JavaScript и является трудноразрешимой проблемой.
В JavaScript для итерации по каждому элементу массива можно использовать метод.forEach(), либо же циклfor в стиле C. Хотя синтаксис.forEach() гораздо более лаконичен и удобен для чтения, он страдает тем недостатком, что функция обратного вызова будет вызываться на каждой итерации массива, и поэтому работает гораздо медленнее, чем эквивалентный циклfor. Синтаксис CoffeeScript обеспечивает ту же выразительность, что и.forEach(), но без ограничений по скорости.
CoffeeScript:
myFunction(item)foriteminarray
#"ltr">
// вариант с forEacharray.forEach(myFunction);// вариант с цикломfor(leti=0;i<array.length;i++){letitem=array[i];myFunction(item);}
В современном JavaScript проверка того, находится ли значение внутри массива, обычно выполняется с помощью метода.includes(). В CoffeeScript для этого можно использовать операторin (который компилируется в метод.indexOf() JavaScript) и, при необходимости, шимминг, чтобы определить, находится ли значение внутри массива.
CoffeeScript:
string="a long test string"included="test"instring
#"ltr">
letstring="a long test string";letincluded=string.includes("test");
Для итерации по объектам в JavaScript используется операторin (для массивов обычно рекомендуется использовать операторof). В CoffeeScript вместо этого оператор был переименован в of, и его можно использовать следующим образом:
Math.max иMath.min принимают несколько аргументов, поэтому можно легко использовать… для передачи им массива, получая максимальное и минимальное значения в массиве.
// два эквивалентных по результату способа; первый:Math.max(...[14,35,-7,46,98]);Math.min(...[14,35,-7,46,98]);// (здесь используется оператор ..., позволяющий разбивать массивы на отдельные значения и напрямую передавать их в функции как параметры)// второй способ:Math.max.apply(null,[14,35,-7,46,98]);Math.min.apply(null,[14,35,-7,46,98]);
В руководствах по стилю CoffeeScript указано, чтоor предпочтительнее, чем||, аand предпочтительнее, чем&&. Это предпочтение более английского стиля также относится к использованиюis вместо== иisnt вместо!=.
Использование внешних библиотек — это то же самое, что вызов функций из библиотек CoffeeScript, поскольку в конечном итоге все компилируется в JavaScript.
CoffeeScript:
# Use local alias$=jQuery$-># DOMContentLoaded$(".el").click->alert("Clicked!")
Ключевое словоdo в CoffeeScript позволяет выполнять функции немедленно, что является отличным способом инкапсуляции области видимости и защиты переменных.
На официальном сайте языка есть раздел «try coffeescript», позволяющий выполнять программы на нём online[4]. В отличие, к примеру, от Try Ruby[5], при этом не будет происходить запросов к серверу, код компилируется и исполняется непосредственно в браузере.
classHumanconstructor:(@name) ->classBabyextendsHumansay:(msg) ->alert"#{@name} говорит '#{msg}'"sayHi:->@say('здравствуй!')matt=newBaby("Матвей")matt.sayHi()
#"ltr">
classHuman{constructor(name){this.name=name;}}classBabyextendsHuman{say(msg){alert(`${this.name} говорит '${msg}'`);}sayHi(){this.say('здравствуй!');}}letmatt=newBaby('Матвей');matt.sayHi();
Аналог на JavaScript (именно аналог, а не результат компиляции):
functionHuman(name){this.name=name;}functionBaby(name){Human.call(this,name);}Baby.prototype=Object.create(Human.prototype);Baby.prototype.say=function(msg){alert(this.name+' говорит '+msg);};Baby.prototype.sayHi=function(){this.say('здравствуй!');};Baby.prototype.constructor=Human;varmatt=newBaby("Матвей");matt.sayHi();
Пример класса CoffeeScript с различными видами свойств.
classTestsay=(msg) ->alertmsg# приватный метод@echo=(msg) ->console.logmsg# статический метод, записан в TestsetHi:(msg) -># динамический метод, записан в Test.prototype@hi=->msg# динамический метод, записан в экземпляр Test
Марк Бейтс. CoffeeScript. Второе дыхание JavaScript = Mark Bates. Programming in CoffeeScript. —М.:ДМК, 2012. — 312 с. —300 экз. —ISBN 978-5-94074-842-7.