CoffeeScript

Из Википедии, бесплатной энциклопедии

CoffeeScript
Изображение логотипа
Класс языка
Появился в 13 декабря 2009
Автор Джереми Ашкенас
Расширение файлов .coffee
Выпуск 2.7.0[1] (24 апреля 2022; 2 года назад (2022-04-24))
Испытал влияние 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

См. также[править | править код]

Примечания[править | править код]

  1. "2.7.0". Архивировано из оригинала 23 июня 2022. Дата обращения: 23 июня 2022.
  2. The coffeescript Open Source Project on Open Hub: Licenses Page — 2006.
  3. Пример на титульной странице официального сайта. Дата обращения: 18 января 2012. Архивировано 9 июня 2017 года.
  4. Try CoffeeScript. coffeescript.org. Дата обращения: 4 января 2016. Архивировано 9 июня 2017 года.
  5. Try Ruby: learn the basics of the Ruby language in your browser. tryruby.org. Дата обращения: 4 января 2016. Архивировано 28 сентября 2011 года.

Литература[править | править код]

Ссылки[править | править код]

Смежные проекты:

  • Компилятор CoffeeScript для Windows
  • CoffeeKup, шаблонизатор и движок для генерации HTML-кода на CoffeeScript.
  • Prepros, компилирует на лету CoffeeScript. Под Windows и OSX (также компилирует LESS, Stylus, Haml, Jade, Markdown, Slim, SASS)