CoffeeScript
Скриптовый язык программирования Из Википедии, свободной энциклопедии
CoffeeScript — язык программирования, транслируемый в JavaScript. CoffeeScript добавляет синтаксический сахар в духе Ruby, Python, Haskell и Erlang для того, чтобы улучшить читаемость кода и уменьшить его размер. CoffeeScript позволяет писать более компактный код по сравнению с JavaScript[3]. JavaScript-код, получаемый трансляцией из CoffeeScript, полностью проходит проверку JavaScript Lint.
![]() | Информация в этой статье или некоторых её разделах устарела. |
CoffeeScript | |
---|---|
![]() | |
Класс языка | |
Появился в | 13 декабря 2009 |
Автор | Джереми Ашкенас |
Расширение файлов |
.coffee |
Выпуск | 2.7.0[1] (24 апреля 2022 ) |
Испытал влияние | JavaScript, Python, Ruby, Haskell, Erlang |
Повлиял на | MoonScript, LiveScript |
Лицензия | лицензия MIT[2] |
Сайт | coffeescript.org |
ОС | кроссплатформенность |
История
Создателем языка является Джереми Ашкенас.
Изначально компилятор был написан на Ruby, но в версии 0.5, которая вышла 21 февраля 2010 года, компилятор был реализован на самом же CoffeeScript.
CoffeeScript был радушно воспринят в Ruby-сообществе. Встроенная поддержка CoffeeScript была добавлена в веб-фреймворк Ruby on Rails с версии 3.1.
Преимущества использования
Использование пробелов как разграничительных знаков(вместо скобок, точек с запятой и прочих), делает CoffeeScript кратким. По сравнению с JavaScript, строка для того же конкретного кода в CoffeeScript сокращается примерно до половины (примерно на 55 % меньше). Так же CoffeeScript позволяет избежать проблем с объявлением области действия в программе, поскольку в отличие от JavaScript использование ключевого слова var перед объявлением переменной не требуется. Помимо этого, в CoffeeScript есть ряд удобных функций, таких как осмысление массивов, псевдонимы прототипов и классы, которые ещё больше сокращают количество вводимых символов.
Недостатки использования
Дополнительный этап компиляции между написанным кодом и кодом на JavaScript увеличивает общее время компиляции программы. CoffeeScript не является широко используемым, из за чего сложнее искать источники информации по нему и кооперировать с другими разработчиками
Синтаксис
Суммиров вкратце
Перспектива
Особенности
- отсутствие точек с запятой (при этом, в самом JavaScript использование точек с запятой не обязательно, хоть и рекомендуется)
- фигурные скобки
{}
заменены табуляцией
Комментарии
В CoffeeScript синтаксис для комментариев заимствован из Ruby, где каждый однострочный комментарий начинается со знака решетки #
, а многострочные комментарии заключены между тремя символами решетки:
CoffeeScript:
# однострочный комментарий
###
многострочный
комментарий
###
JavaScript:
// однострочный комментарий
/*
многострочный
комментарий
*/
Пробелы
Подобно языку Python, CoffeeScript использует табуляции для обозначения блоков кода.
Переменные
Неподдерживаемость CoffeeScript глобальных переменных предотвращает ошибки доступа, которые могли возникнуть в JavaScript при случайном объявлении глобальной переменной.
CoffeeScript:
myVariable = "test"
JavaScript:
let myVariable = "test";
Функции
CoffeeScript удаляет довольно многословный оператор функции и заменяет его тонкой стрелкой: ->. Функции могут быть однострочными или отступать на несколько строк. Последнее выражение в функции неявно возвращается.
CoffeeScript:
func = -> "bar"
func = ->
# An extra line
"bar"
JavaScript:
function func() {
return "bar";
}
// другой вариант (с использованием стрелочной функции)
let func = () => "bar";
Аргументы функций
Аргументы функции записываются в круглые скобки перед стрелкой. Есть поддержка аргументов по умолчанию.
CoffeeScript:
times = (a = 1, b) -> a * b
JavaScript:
function times(a = 1, b) {
return a * b;
}
// другой вариант
let times = (a = 1, b) => a * b;
Также можно использовать слайсы[прояснить] для приема нескольких аргументов.
CoffeeScript:
a = "Howdy!"
alert a
# Equivalent to:
alert(a)
alert inspect a
# Equivalent to:
alert(inspect(a))
JavaScript:
let a = "Howdy!";
alert(a);
alert(inspect(a));
Вызов функций
Функции можно вызывать точно так же, как и в JavaScript: с помощью скобок ()
, .apply()
и .call()
. Однако, как и в Ruby, CoffeeScript автоматически вызывает функции, если они вызываются хотя бы с одним аргументом.
Объектные литералы и объявление массивов
Объектные литералы задаются точно так же, как и в 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:
let object1 = {
one: 1,
two: 2
}
let object2 = {
one: 1,
two: 2
}
let object3 = {
one: 1,
two: 2
}
User.create({
name: "John Smith"
});
Аналогично, в массивах вместо запятых могут использоваться пробельные символы, хотя квадратные скобки ([]
) по-прежнему обязательны.
CoffeeScript:
array1 = [1, 2, 3]
array2 = [
1
2
3
]
array3 = [1,2,3,]
JavaScript:
let array1 = [1, 2, 3];
let array2 = [
1,
2,
3
];
let array3 = [1, 2, 3,];
Условные операторы
Если оператор if
расположен в одной строке, необходимо использовать ключевое слово then, чтобы CoffeeScript знал, когда начинается блок. Условные операторы (?:) не поддерживаются, вместо них следует использовать однострочный оператор if
/else
.
CoffeeScript:
if true == true
alert "We're ok"
if true != true then alert "Panic"
# Equivalent to:
# (1 > 0) ? alert "Ok" : alert "Y2K!"
if 1 > 0 then alert "Ok" else alert "Y2K!"
JavaScript:
if (true === true) {
alert("We're ok");
}
if (true !== true) {
alert("Panic");
}
if (1 > 0) {
alert("Ok");
} else {
alert("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 alert "Panic"
unless true
alert "Panic"
JavaScript:
if (!true) {
alert("Panic");
}
Аналогично not, в CoffeeScript также вводится оператор is
, который работает как ===
в JavaScript.
CoffeeScript:
if true is 1
alert "Type coercion fail!"
JavaScript:
if (true === 1) {
alert("Type coercion fail!");
}
Интерполяция строк
CoffeeScript поддерживает интерполяцию строк (то есть вставка значения переменной в качестве текста внутрь строки): делается это посредством использования #{}
внутри строки, заключённой в двойные кавычки. На момент выхода CoffeeScript у JavaScript не было такой возможности, однако с выходом стандарта ECMAScript 6 в 2015 году возможность так делать появилась и в JavaScript: для этого строка должна заключаться в специальные кавычки ``
(машинописный обратный апостроф), а вставка переменных производится с использованием ${}
.
CoffeeScript:
favourite_color = "Blue. No, yel..."
question = "Bridgekeeper: What... is your favourite color?
Galahad: #{favourite_color}
Bridgekeeper: Wrong!
"
JavaScript:
let favouriteColor = "Blue. No, yel...";
let question = `Bridgekeeper: What... is your favourite color?
Galahad: ${favouriteColor}
Bridgekeeper: Wrong!
`;
Массивы
CoffeeScript черпает вдохновение из Ruby, когда речь идет о создании массивов с помощью диапазонов. Диапазоны создаются двумя числовыми значениями, первой и последней позициями в диапазоне, разделенными ..
. Если диапазон не имеет никакого префикса, CoffeeScript расширяет его до массива.
CoffeeScript:
range = [1..5]
JavaScript:
let 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:
let firstTwo = ["one", "two", "three"].slice(0, 2);
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
numbers = [...numbers.slice(0, 3), -3, -4, -5, ...numbers.slice(6)];
let my = "my string".slice(0, 3);
Для проверки наличия значения внутри массива в JavaScript можно использовать метод .includes()
. В CoffeeScript для этого есть специальный оператор in
.
CoffeeScript:
words = ["rattled", "roudy", "rebbles", "ranks"]
alert "Stop wagging me" if "ranks" in words
JavaScript:
let words = ["rattled", "roudy", "rebbles", "ranks"];
if (words.includes("ranks")) {
alert("Stop wagging me");
}
Классы
Суммиров вкратце
Перспектива
Ключевое слово class
было добавлено в JavaScript в стандарте ECMAScript 6. При этом, JavaScript и до этого поддерживал классы (за счёт использования прототипов), а само ключевое слово class
является синтаксическим сахаром:
class Person {
constructor(name) {
this.name = name;
}
say(phrase) {
return `${this.name} говорит ${phrase}`;
}
}
// Данный код полностью эквивалентен следующему коду:
function Person(name) {
this.name = name;
}
Person.prototype.say = function(phrase) {
return this.name + " говорит " + phrase;
}
Далее для JavaScript-кода в данном разделе будет использоваться синтаксис с использованием class
.
CoffeeScript использует собственный прототип JavaScript для создания классов, добавляя немного синтаксического сахара для наследования статических свойств и сохранения контекста. В CoffeeScript используются функции-конструкторы, что означает возможность инстанцирования классов с помощью оператора new. CoffeeScript предоставляет сокращение для общего шаблона установки свойств экземпляра класса. Префикс аргумента @ позволяет CoffeeScript автоматически устанавливать аргументы как свойства экземпляра в конструкторе.
CoffeeScript:
class Animal
constructor: (@name) ->
JavaScript:
class Animal {
constructor(name) {
this.name = name;
}
}
Свойства экземпляра
Добавление дополнительных свойств экземпляра в класс очень просто, это точно такой же синтаксис, как и добавление свойств к объекту. Свойства должны быть правильно расположены с отступом внутри тела класса.
CoffeeScript:
class Animal
price: 5
sell: (customer) ->
animal = new Animal
animal.sell(new Customer)
JavaScript:
class Animal {
price = 5;
sell(customer) {}
}
let animal = new Animal();
animal.sell(new Customer());
Статичные свойства
Внутри определения класса, ключевое слово this
и @
ссылаются на объект класса.
CoffeeScript:
class Animal
this.find_ = (name) ->
@.age_ = (age) ->
Animal.find_("Parrot")
JavaScript:
class Animal {
static find_(name) {}
static age_(age) {}
}
Animal.find_("Parrot");
Наследование
Наследование класса происходит при помощи ключевого слова extends
.
CoffeeScript:
class Animal
constructor: (@name) ->
alive: ->
false
class Parrot extends Animal
constructor: ->
super("Parrot")
dead: ->
not @alive()
JavaScript:
class Animal {
constructor(name) {
this.name = name;
}
alive() {
return false;
}
}
class Parrot extends Animal {
constructor() {
super("Parrot");
}
dead() {
return !this.alive();
}
}
Статические свойства копируются в подклассы, а не наследуются по прототипу, как свойства экземпляра. Это связано с особенностями реализации прототипической архитектуры JavaScript и является трудноразрешимой проблемой.
Идиомы
Суммиров вкратце
Перспектива
Each
В JavaScript для итерации по каждому элементу массива можно использовать метод .forEach()
, либо же цикл for
в стиле C. Хотя синтаксис .forEach()
гораздо более лаконичен и удобен для чтения, он страдает тем недостатком, что функция обратного вызова будет вызываться на каждой итерации массива, и поэтому работает гораздо медленнее, чем эквивалентный цикл for
. Синтаксис CoffeeScript обеспечивает ту же выразительность, что и .forEach()
, но без ограничений по скорости.
CoffeeScript:
myFunction(item) for item in array
JavaScript:
// вариант с forEach
array.forEach(myFunction);
// вариант с циклом
for (let i = 0; i < array.length; i++) {
let item = array[i];
myFunction(item);
}
Includes
В современном JavaScript проверка того, находится ли значение внутри массива, обычно выполняется с помощью метода .includes()
. В CoffeeScript для этого можно использовать оператор in
(который компилируется в метод .indexOf()
JavaScript) и, при необходимости, шимминг, чтобы определить, находится ли значение внутри массива.
CoffeeScript:
string = "a long test string"
included = "test" in string
JavaScript:
let string = "a long test string";
let included = string.includes("test");
Итерации
Для итерации по объектам в JavaScript используется оператор in
(для массивов обычно рекомендуется использовать оператор of
). В CoffeeScript вместо этого оператор был переименован в of, и его можно использовать следующим образом:
CoffeeScript:
object = {one: 1, two: 2}
alert("#{key} = #{value}") for key, value of object
JavaScript:
let object = {
one: 1,
two: 2
};
for (let key in object) {
let 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(...[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]);
And/or
В руководствах по стилю CoffeeScript указано, что or
предпочтительнее, чем ||
, а and
предпочтительнее, чем &&
. Это предпочтение более английского стиля также относится к использованию is
вместо ==
и isnt
вместо !=
.
CoffeeScript:
string = "migrating coconuts"
string == string # true
string is string # true
JavaScript:
let string = "migrating coconuts";
string === string;
string === string;
Внешние библиотеки
Использование внешних библиотек — это то же самое, что вызов функций из библиотек CoffeeScript, поскольку в конечном итоге все компилируется в JavaScript.
CoffeeScript:
# Use local alias
$ = jQuery
$ ->
# DOMContentLoaded
$(".el").click ->
alert("Clicked!")
JavaScript:
let $ = jQuery;
$(function() {
return $(".el").click(function() {
return alert("Clicked!");
});
});
Локальные переменные
Ключевое слово 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:
const say = 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:
class Human {
constructor(name) {
this.name = name;
}
}
class Baby extends Human {
say(msg) {
alert(`${this.name} говорит '${msg}'`);
}
sayHi() {
this.say('здравствуй!');
}
}
let 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();
Пример класса CoffeeScript с различными видами свойств.
class Test
say = (msg) -> alert msg # приватный метод
@echo = (msg) -> console.log msg # статический метод, записан в Test
setHi: (msg) -> # динамический метод, записан в Test.prototype
@hi = -> msg # динамический метод, записан в экземпляр Test
Компилятор
Интересным является тот факт, что компилятор для CoffeeScript написан на самом CoffeeScript
См. также
Примечания
Литература
Ссылки
Wikiwand - on
Seamless Wikipedia browsing. On steroids.