CoffeeScript — Википедия
CoffeeScript | |
---|---|
Класс языка | |
Появился в | 13 декабря 2009 |
Автор | Джереми Ашкенас |
Расширение файлов | .coffee |
Выпуск | 2.7.0[1] (24 апреля 2022 ) |
Испытал влияние | JavaScript, Python, Ruby, Haskell, Erlang |
Повлиял на | MoonScript, LiveScript |
Лицензия | лицензия MIT[2] |
Сайт | coffeescript.org |
ОС | кроссплатформенность |
CoffeeScript ([’kɔ:fɪ skrɪpt]; кофи скрипт) — язык программирования, транслируемый в JavaScript. CoffeeScript добавляет синтаксический сахар в духе Ruby, Python, Haskell и Erlang для того, чтобы улучшить читаемость кода и уменьшить его размер. CoffeeScript позволяет писать более компактный код по сравнению с JavaScript[3]. JavaScript-код, получаемый трансляцией из CoffeeScript, полностью проходит проверку JavaScript Lint.
История
[править | править код]Создателем языка является Джереми Ашкенас.
Изначально компилятор был написан на Ruby, но в версии 0.5, которая вышла 21 февраля 2010 года, компилятор был реализован на самом же CoffeeScript.
CoffeeScript был радушно воспринят в Ruby-сообществе. Встроенная поддержка CoffeeScript была добавлена в веб-фреймворк Ruby on Rails с версии 3.1.
Преимущества использования
[править | править код]Использование пробелов как разграничительных знаков(вместо скобок, точек с запятой и прочих), делает CoffeeScript кратким. По сравнению с JavaScript, строка для того же конкретного кода в CoffeeScript сокращается примерно до половины (примерно на 55 % меньше). Так же CoffeeScript позволяет избежать проблем с объявлением области действия в программе, поскольку в отличие от JavaScript использование ключевого слова var перед объявлением переменной не требуется. Помимо этого, в CoffeeScript есть ряд удобных функций, таких как осмысление массивов, псевдонимы прототипов и классы, которые ещё больше сокращают количество вводимых символов.
Недостатки использования
[править | править код]Дополнительный этап компиляции между написанным кодом и кодом на JavaScript увеличивает общее время компиляции программы. CoffeeScript не является широко используемым, из за чего сложней искать источники информации по нему и кооперировать с другими разработчиками
Синтаксис
[править | править код]Особенности
[править | править код]— отсутствие точек с запятой
— фигурные скобки ({}) заменены табуляцией
Комментарии
[править | править код]Синтаксис для комментариев заимствован из Ruby, где каждый однострочный комментарий начинается со знака решетки «#», а многострочные комментарии заключены между тремя символами решетки:
# A single line comment ### A multiline comment ###
Пробелы
[править | править код]Вдохновившись Python, в CoffeeScript вместо фигурных скобок используется табуляция
Переменные
[править | править код]Неподдерживаемость CoffeeScript глобальных переменных предотвращает ошибки доступа, которые могли возникнуть в JavaScript при случайном объявлении глобальной переменной.
CoffeeScript:
myVariable = "test"
JavaScript:
var myVariable; myVariable = "test";
Функции
[править | править код]CoffeeScript удаляет довольно многословный оператор функции и заменяет его тонкой стрелкой: ->. Функции могут быть однострочными или отступать на несколько строк. Последнее выражение в функции неявно возвращается.
CoffeeScript:
func = -> "bar"
CoffeeScript:
func = -> # An extra line "bar"
JavaScript:
var func; func = function() { return "bar"; };
Аргументы функций
[править | править код]Аргументы функции записываются в круглые скобки перед стрелкой. Есть поддержка аргументов по умолчанию.
CoffeeScript:
times = (a = 1, b) -> a * b
JavaScript:
var times; times = function(a, b) { if(a == null){ a = 1; } return a * b; };
Так же можно использовать слайсы для приема нескольких аргументов CoffeeScript:
a = "Howdy!" alert a # Equivalent to: alert(a) alert inspect a # Equivalent to: alert(inspect(a))
JavaScript:
var a; a = "Howdy!"; alert(a); alert(a); alert(inspect(a)); alert(inspect(a));
Вызов функций
[править | править код]Функции можно вызывать точно так же, как и в JavaScript, с помощью скобок (), apply() или call(). Однако, как и в Ruby, CoffeeScript автоматически вызывает функции, если они вызываются хотя бы с одним аргументом.
CoffeeScript:
myVariable = "test"
JavaScript:
var myVariable; myVariable = "test";
Объектные литералы и объявление массивов
[править | править код]Объектные литералы задаются точно так же, как и в JavaScript, с помощью пары скобок и операторов ключ/значение. Однако, как и в случае с вызовом функций, в CoffeeScript скобки необязательны. Вместо запятых можно использовать отступы и новые строки.
CoffeeScript:
object1 = {one: 1, two: 2} # Without braces object2 = one: 1, two: 2 # Using new lines instead of commas object3 = one: 1 two: 2 User.create(name: "John Smith")
JavaScript:
var object1, object2, object3; object1 = { one: 1, two: 2 }; object2 = { one: 1, two: 2 }; object3 = { one: 1, two: 2 }; User.create({ name: "John Smith" });
Аналогично, в массивах вместо запятых могут использоваться пробельные символы, хотя квадратные скобки ([]) по-прежнему обязательны. CoffeeScript:
array1 = [1, 2, 3] array2 = [ 1 2 3 ] array3 = [1,2,3,]
JavaScript:
var array1, array2, array3; array1 = [1, 2, 3]; array2 = [1, 2, 3]; array3 = [1, 2, 3];
Условные операторы
[править | править код]Если оператор if расположен в одной строке, необходимо использовать ключевое слово then, чтобы CoffeeScript знал, когда начинается блок. Условные операторы (?:) не поддерживаются, вместо них следует использовать однострочный оператор if/else.
CoffeeScript:
if true == true "We're ok" if true != true then "Panic" # Equivalent to: # (1 > 0) ? "Ok" : "Y2K!" if 1 > 0 then "Ok" else "Y2K!"
JavaScript:
if (true === true) { "We're ok"; } if (true !== true) { "Panic"; } if (1 > 0) { "Ok"; } else { "Y2K!"; }
В CoffeeScript также используется идиома Ruby, позволяющая использовать суффиксные операторы if. CoffeeScript:
alert "It's cold!" if heat < 5
JavaScript:
if (heat < 5) { alert("It's cold!"); }
Вместо восклицательного знака (!) для отрицания можно также использовать ключевое слово not или оператор unless CoffeeScript:
if not true then "Panic"
unless true "Panic"
JavaScript:
if (!true) { "Panic"; }
Аналогично not, в CoffeeScript также вводится оператор is, который работает как === в JavaScript. CoffeeScript:
if true is 1 "Type coercion fail!"
JavaScript:
if (true === 1) { "Type coercion fail!"; }
Интерполяция строк
[править | править код]CoffeeScript привносит в JavaScript интерполяцию строк в стиле Ruby. Строки в двойных кавычках могут содержать теги #{}, которые содержат выражения, подлежащие интерполяции в строку.
CoffeeScript:
favourite_color = "Blue. No, yel..." question = "Bridgekeeper: What... is your favourite color? Galahad: #{favourite_color} Bridgekeeper: Wrong! "
JavaScript:
var favourite_color, question; favourite_color = "Blue. No, yel..."; question = "Bridgekeeper: What... is your favourite color? Galahad: " + favourite_color + " Bridgekeeper: Wrong! ";
Циклы и вычисления
[править | править код]…
CoffeeScript:
JavaScript:
Массивы
[править | править код]CoffeeScript черпает вдохновение из Ruby, когда речь идет о создании массивов с помощью диапазонов. Диапазоны создаются двумя числовыми значениями, первой и последней позициями в диапазоне, разделенными … или ….. Если диапазон не имеет никакого префикса, CoffeeScript расширяет его до массива.
CoffeeScript:
range = [1..5]
JavaScript:
var range; range = [1, 2, 3, 4, 5];
Если же диапазон указывается сразу после переменной, то CoffeeScript преобразует его в вызов метода slice().
CoffeeScript:
firstTwo = ["one", "two", "three"][0..1]
numbers = [0..9] numbers[3..5] = [-3, -4, -5]
my = "my string"[0..2]
JavaScript:
var firstTwo; firstTwo = ["one", "two", "three"].slice(0, 2);
var numbers, _ref; numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; [].splice.apply(numbers, [3, 3].concat(_ref = [-3, -4, -5])), _ref;
var my; my = "my string".slice(0, 3);
Проверка наличия значения внутри массива всегда является проблемой в JavaScript, тем более что функция indexOf() пока не имеет полной кроссбраузерной поддержки. В CoffeeScript эта проблема решается с помощью оператора in:
CoffeeScript:
words = ["rattled", "roudy", "rebbles", "ranks"] alert "Stop wagging me" if "ranks" in words
JavaScript:
var words; var __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (this[i] === item) return i; } return -1; }; words = ["rattled", "roudy", "rebbles", "ranks"]; if (__indexOf.call(words, "ranks") >= 0) { alert("Stop wagging me"); }
Классы
[править | править код]CoffeeScript использует собственный прототип JavaScript для создания классов, добавляя немного синтаксического сахара для наследования статических свойств и сохранения контекста. В CoffeeScript используются функции-конструкторы, что означает возможность инстанцирования классов с помощью оператора new. CoffeeScript предоставляет сокращение для общего шаблона установки свойств экземпляра класса. Префикс аргумента @ позволяет CoffeeScript автоматически устанавливать аргументы как свойства экземпляра в конструкторе.
CoffeeScript:
class Animal constructor: (@name) ->
JavaScript:
var Animal; Animal = (function() { function Animal(name) { this.name = name; } return Animal; })();
Свойства экземпляра
[править | править код]Добавление дополнительных свойств экземпляра в класс очень просто, это точно такой же синтаксис, как и добавление свойств к объекту. Свойства должны быть правильно расположены с отступом внутри тела класса.
CoffeeScript:
class Animal price: 5 sell: (customer) -> animal = new Animal animal.sell(new Customer)
JavaScript:
var Animal, animal; Animal = (function() { function Animal() {} Animal.prototype.price = 5; Animal.prototype.sell = function(customer) {}; return Animal; })(); animal = new Animal; animal.sell(new Customer);
Статичные свойства
[править | править код]Внутри определения класса, ключевое слово this и @ ссылаются на объект класса
CoffeeScript:
class Animal this.find_ = (name) -> @.age_ = (age) -> Animal.find_("Parrot")
JavaScript:
var Animal; Animal = (function() { function Animal() {} Animal.find_ = function(name) {}; Anumal.age_ = functiona(age){}; return Animal; })(); Animal.find_("Parrot");
Наследование
[править | править код]Наследование класса происходит при помощи ключевого слова extends
CoffeeScript:
class Animal constructor: (@name) -> alive: -> false class Parrot extends Animal constructor: -> super("Parrot") dead: -> not @alive()
JavaScript:
var Animal, Parrot; var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; Animal = (function() { function Animal(name) { this.name = name; } Animal.prototype.alive = function() { return false; }; return Animal; })(); Parrot = (function() { __extends(Parrot, Animal); function Parrot() { Parrot.__super__.constructor.call(this, "Parrot"); } Parrot.prototype.dead = function() { return !this.alive(); }; return Parrot; })();
Cтатические свойства копируются в подклассы, а не наследуются по прототипу, как свойства экземпляра. Это связано с особенностями реализации прототипической архитектуры JavaScript и является трудноразрешимой проблемой.
Each
[править | править код]В JavaScript для итерации по каждому элементу массива можно использовать либо недавно добавленную функцию forEach(), либо же цикл for в стиле C. Хотя синтаксис forEach() гораздо более лаконичен и удобен для чтения, он страдает тем недостатком, что функция обратного вызова будет вызываться на каждой итерации массива, и поэтому работает гораздо медленнее, чем эквивалентный цикл for. Синтаксис CoffeeScript обеспечивает ту же выразительность, что и forEach(), но без ограничений по скорости.
CoffeeScript:
myFunction(item) for item in array
JavaScript:
var item, _i, _len; for (_i = 0, _len = array.length; _i < _len; _i++) { item = array[_i]; myFunction(item); }
Includes
[править | править код]Проверка того, находится ли значение внутри массива, обычно выполняется с помощью функции indexOf(). CoffeeScript использует Array.prototype.indexOf() и, при необходимости, шимминг, чтобы определить, находится ли значение внутри массива. К сожалению, это означает, что аналогичный синтаксис не будет работать для строк. Приходится возвращаться к использованию indexOf() и проверять, не будет ли результат отрицательным или, что ещё лучше, использовать побитовый оператор, чтобы не делать сравнение −1.
CoffeeScript:
string = "a long test string" included = !!~ string.indexOf "test"
JavaScript:
var included, string; string = "a long test string"; included = !!~string.indexOf("test");
Итерации
[править | править код]Для итерации в JavaScript используется оператор in. В CoffeeScript Вместо этого оператор был переименован в of, и его можно использовать следующим образом:
CoffeeScript:
object = {one: 1, two: 2} alert("#{key} = #{value}") for key, value of object
JavaScript:
var key, object, value; object = { one: 1, two: 2 }; for (key in object) { value = object[key]; alert("" + key + " = " + value); }
Min/Max
[править | править код]Math.max и Math.min принимают несколько аргументов, поэтому можно легко использовать … для передачи им массива, получая максимальное и минимальное значения в массиве.
CoffeeScript:
Math.max [14, 35, -7, 46, 98]... # 98 Math.min [14, 35, -7, 46, 98]... # -7
JavaScript:
Math.max.apply(Math, [14, 35, -7, 46, 98]); Math.min.apply(Math, [14, 35, -7, 46, 98]);
And/or
[править | править код]В руководствах по стилю CoffeeScript указано, что or предпочтительнее, чем ||, а and предпочтительнее, чем &&. Это предпочтение более английского стиля также относится к использованию is вместо == и isnt вместо !=. Одним из чрезвычайно приятных дополнений к CoffeeScript является 'or equals' — паттерн, который рубинисты могут узнать как ||=:
CoffeeScript:
string = "migrating coconuts" string == string # true string is string # true
JavaScript:
var string; string = "migrating coconuts"; string === string; string === string;
Внешние библиотеки
[править | править код]Использование внешних библиотек — это то же самое, что вызов функций из библиотек CoffeeScript, поскольку в конечном итоге все компилируется в JavaScript.
CoffeeScript:
# Use local alias $ = jQuery $ -> # DOMContentLoaded $(".el").click -> alert("Clicked!")
JavaScript:
var $; $ = jQuery; $(function() { return $(".el").click(function() { return alert("Clicked!"); }); });
Private variables
[править | править код]Ключевое слово do в CoffeeScript позволяет выполнять функции немедленно, что является отличным способом инкапсуляции области видимости и защиты переменных.
Реализация
[править | править код]На официальном сайте языка есть раздел «try coffeescript», позволяющий выполнять программы на нём online[4]. В отличие, к примеру, от Try Ruby[5], при этом не будет происходить запросов к серверу, код компилируется и исполняется непосредственно в браузере.
Примеры
[править | править код]Переменные
[править | править код]CoffeeScript:
age = 2 male = true name = "Матвей"
JavaScript:
let age = 2, male = true, name = "Матвей";
Функции
[править | править код]CoffeeScript:
say = (speech) -> alert speech say "Привет мир!"
JavaScript с использованием ECMAScript 2015:
const say = speech => alert(speech); say('Привет мир!');
JavaScript:
var say = function(speech) { alert(speech); }; say("Привет мир!");
Классы и объекты
[править | править код]CoffeeScript:
class Human constructor : (@name) -> class Baby extends Human say : (msg) -> alert "#{@name} говорит '#{msg}'" sayHi : -> @say('здравствуй!') matt = new Baby("Матвей") matt.sayHi()
JavaScript с использованием ECMAScript 2015:
class Human { constructor(name) { this.name = name; } } class Baby extends Human { say(msg) { alert(`${this.name} говорит '${msg}'`); } sayHi() { this.say('здравствуй!'); } } const matt = new Baby('Матвей'); matt.sayHi();
Аналог на JavaScript (именно аналог, а не результат компиляции):
function Human(name){ this.name = name; } function Baby(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; var matt = new Baby("Матвей"); matt.sayHi();
Примечание: в JavaScript при работе с «классами» (конструктор + прототипы + функции для наследования и смешивания) часто используют обёртки (MooTools, AtomJS и другие). Аналогия на JavaScript с классовой обёрткой AtomJS:
var Human = Class({ initialize : function(name) { this.name = name; } }); var Baby = Class({ Extends : Human, say : function(msg) { alert(this.name + ' говорит ' + msg); }, sayHi : function() { this.say('здравствуй!'); } }); var matt = new Baby("Матвей"); matt.sayHi();
Пример класса CoffeeScript с различными видами свойств.
class Test say = (msg) -> alert msg # приватный метод @echo = (msg) -> console.log msg # статический метод, записан в Test setHi : (msg) -> # динамический метод, записан в Test.prototype @hi = -> msg # динамический метод, записан в экземпляр Test
Компилятор
[править | править код]Интересным является тот факт, что компилятор для CoffeeScript написан на самом CoffeeScript
См. также
[править | править код]Примечания
[править | править код]- ↑ "2.7.0". Архивировано 23 июня 2022. Дата обращения: 23 июня 2022.
- ↑ The coffeescript Open Source Project on Open Hub: Licenses Page — 2006.
- ↑ Пример на титульной странице официального сайта . Дата обращения: 18 января 2012. Архивировано 9 июня 2017 года.
- ↑ Try CoffeeScript . coffeescript.org. Дата обращения: 4 января 2016. Архивировано 9 июня 2017 года.
- ↑ Try Ruby: learn the basics of the Ruby language in your browser. tryruby.org. Дата обращения: 4 января 2016. Архивировано 28 сентября 2011 года.
Литература
[править | править код]- Марк Бейтс. CoffeeScript. Второе дыхание JavaScript = Mark Bates. Programming in CoffeeScript. — М.: ДМК, 2012. — 312 с. — 300 экз. — ISBN 978-5-94074-842-7.
- Alex MacCaw. The Little Book on CoffeeScript. — O'Reilly Media, 2011. — 60 с. — ISBN 9781449321055,.
- CoffeeScript Cookbook, сборник рецептов CoffeeScript от сообщества.
- Smooth CoffeeScript Архивная копия от 11 июля 2011 на Wayback Machine, свободная электронная книга о CoffeeScript. Доступна в двух вариантах с исходным кодом примеров.
- Майкл Галпин. Ваша первая чашечка CoffeeScript : Часть 1. Приступаем к работе . DeveloperWorks (19 июля 2012). Дата обращения: 10 января 2016.
- Ваша первая чашечка CoffeeScript: Часть 2. Изучение языка на практических примерах (18 июля 2012). Дата обращения: 10 января 2016.
- Ваша первая чашечка CoffeeScript: Часть 3. Использование CoffeeScript на стороне клиента (20 июля 2012). Дата обращения: 10 января 2016.
- Ваша первая чашечка CoffeeScript: Часть 4. Использование CoffeeScript на стороне сервера (20 июля 2012). Дата обращения: 10 января 2016.
- Эндрю Гловер. Функциональный JavaScript с применением CoffeeScript и Node . DeveloperWorks (3 декабря 2012). Дата обращения: 10 января 2016.
- Alex MacCaw. The Little Book on CoffeeScript
Ссылки
[править | править код]- Официальный сайт CoffeeScript
- Репозиторий CoffeeScript на GitHub
- Перевод официальной документации
- Русскоязычная группа по CoffeeScript
- Русскоязычный сайт по CoffeeScript
- Видеокурс (ru)
Смежные проекты:
- Компилятор CoffeeScript для Windows
- CoffeeKup, шаблонизатор и движок для генерации HTML-кода на CoffeeScript.
- Prepros, компилирует на лету CoffeeScript. Под Windows и OSX (также компилирует LESS, Stylus, Haml, Jade, Markdown, Slim, SASS)