Статьи

Spider: захватывающая альтернатива JavaScript

Spider — один из новых языков, которые пытаются улучшить наши коды, обеспечивая большую надежность. Некоторые, конечно, могут описать его как CoffeeScript с синтаксисом JavaScript, но такое описание не сможет подчеркнуть реальные преимущества Spider.

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

Основные понятия

Spider разработан вокруг своего слогана, это просто JavaScript, но лучше. Это означает, что мы не получим систему типов компиляции или проверку типов. Мы также не пропустим наш любимый синтаксис в стиле C с фигурными скобками для блоков, круглыми скобками для вызовов функций и квадратными скобками для массивов. Наконец, мы также не видим пользовательскую виртуальную машину поверх JavaScript или что-либо еще, что нарушает совместимость с существующим кодом JavaScript. Да, это действительно JavaScript.

Создатели Spider поняли, что нет смысла обсуждать статические и динамические языки. У каждого есть свои преимущества и недостатки. Причина выбора полной динамической стороны в Spider проста: JavaScript уже динамичен и взаимодействует с другим, в противном случае динамический код становится намного проще, когда язык охватывает динамическую систему типов.

Здесь следует упомянуть еще две важные вещи:

  1. Spider компилируется в JavaScript (то есть переносится)
  2. Некоторые функции основаны на таких языках, как Go, C # и CoffeeScript.

Файлы передаются не в более старые версии JavaScript, а в самый последний стандартный ECMAScript 6. Чтобы гарантировать поддержку большинства браузеров, Spider использует Google Traceur для создания файлов, совместимых с ECMAScript 5. Это означает, что Spider уже использует преимущества будущих улучшений с текущей обратной совместимостью.

Синтаксис

Spider включает в себя оператор :: для доступа к глобальной области видимости. Это мешает нам делать что-то глупое, не осознавая этого. Однако это также означает, что нам нужно написать немного больше для доступа, например, к объекту console . Нижеприведенный оператор показывает пример, который использует оператор :::

 ::console.log("Hello world!"); 

Возможный способ обойти это — использовать оператор use . Это позволяет нам ссылаться на локально необъявленный символ.

 use console; console.log("Hello world!"); 

Spider предоставляет определенные макросы, которые разблокируют некоторые известные глобальные объекты. В зависимости от типа приложения, которое вы разрабатываете, эти макросы могут быть более или менее полезными. Одним из примеров является следующее:

 use :browser; console.log(document.title, window.screen); 

Макрос :browser позволяет нам напрямую использовать такие объекты, как document , console , window , location и многие другие. Очень полезная функция для приложений, интенсивно использующих DOM.

Вместо того чтобы сохранить все прежние логические операторы, некоторые были заменены. Например, операторы равенства и неравенства ( == и != ) Теперь играют роль строгого равенства и строгого неравенства ( === и !== в JavaScript). Операторы «и» ( && ) и «или» ( || ) также преобразуют значение и были переименованы в and и or соответственно. Вот пример:

 // x == true; x = false or 5; // x == true; x = 5 and 4; // x == false; x = 1 == "1"; 

Теперь некоторые из вас будут кричать, перестанут читать эту статью, а также закроют страницу. Но подождите … не уходите так быстро!

Логические и и логические операторы также использовались для управления потоком и размещения значений по умолчанию. В то время как первый не так интересен, последний может реально сэкономить время. Язык использует нуль-объединяющий оператор ?? из C # для покрытия значений по умолчанию:

 x = options.name ?? 'default name'; 

На данный момент мы готовы взглянуть на функции. Именно функции делают JavaScript таким интересным. Паук не забирает ничего, кроме нескольких символов:

 var square = fn (x) { return x * x; }; 

Вместо написания function , в Spider мы можем написать fn . Это избавляет нас от набора нескольких нажатий клавиш при сохранении той же структуры. Как и в JavaScript, мы можем использовать функции в выражениях функций или в выражениях функций. Операторы функций ограничены именованными функциями, как в JavaScript.

Кроме того, мы можем использовать функцию arrow -> как в лямбда-выражениях Java (и аналогично функциям стрелки в JavaScript). Предыдущий пример можно выразить следующим образом:

 var square = (x) -> x * x; 

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

Но простой функции стрелка недостаточно. Как и в языке TypeScript (а также в ECMAScript 6), у нас также есть жирная стрелка => . Это функция сохранения контекста стрелка. Если вы хотите узнать больше о функциях стрелок в JavaScript, я предлагаю вам прочитать статью Подготовка к ECMAScript 6: Новый синтаксис функций .

Ниже приведен пример этого оператора в Spider:

 fn Animal(name) { this.name = name; this.printNameLater = () => { ::setTimeout(() => { ::console.log(this.name); }, 1000); }; } 

Еще одно замечание для функций — это возможность задавать параметры по умолчанию и использовать остальные параметры, как в ECMAScript 6. Первый автоматически генерирует код для проверки и исправления отсутствующих (то есть undefined ) аргументов. Последнее похоже на списки переменных аргументов. Он в основном группирует все дополнительные безымянные параметры в один именованный массив:

 fn format(text, parameters...) { for parameter, index in parameters text = text.replace('{' + index + '}', parameter); return text; } format("Hi {0}! My name is {1}.", "World", "Florian"); 

В предыдущем примере мы также видели один из элегантных способов Spider написать цикл. Мы использовали классический цикл foreach с дополнительным счетчиком итераций. Spider также содержит больше таких функций, как мы увидим в следующем разделе.

Характеристики

Spider обеспечивает гораздо большую безопасность JavaScript, обеспечивая большую согласованность. Пример для более последовательного подхода можно найти в названии типов.

 // "object" typeof { a: 4 }; // "array" typeof [1, 2, 3]; // "date" typeof new Date; // "number" typeof new Number(4); // "string" typeof new String("abc"); // "boolean" typeof new Boolean(true); 

Как вы можете видеть, тип для массивов и дат отличается от JavaScript и более близок к тому, что вы (или большинство людей) ожидаете. Еще одну проверку безопасности можно найти у экзистенциального оператора ? , Он преобразует любое выражение в проверку на null или undefined . Это может быть очень удобно:

 if game? { play(); } 

Есть и другие варианты, а именно ?. (также называемый оператором Элвиса) для вызова свойств или ?() для вызова функций. Следовательно, следующее может иметь смысл:

 game?.play?(); 

Здесь мы получаем доступ только к свойству play если game определена. Если play не является функцией, то ничего не вызывается.

Transpilation

Я уже упоминал, что Spider на самом деле переносится в ECMAScript 6. Как положительный побочный эффект, Spider вполне пригоден для будущего и использует функции JavaScript, которые доступны сегодня. Однако при настройке ES6 есть и недостаток: нам все еще нужен другой транспортер для преобразования вывода в ES5 или ниже, что может интерпретироваться всеми современными браузерами (включая более старые версии Internet Explorer).

Для транспиляции нам нужен компилятор Spider. Лучшее решение — установить spider-скрипт пакета npm :

 npm install -g spider-script 

Это также устанавливает Traceur, PEG.js и кучу других зависимостей. Основным недостатком использования Traceur является дополнительная зависимость во время выполнения.

На данный момент у нас есть доступ к компилятору Spider, который называется spider . По умолчанию компилятор переносит и запускает код в режиме ES5, не затрагивая диск. Однако есть несколько вариантов изменить это поведение и записать выходные файлы с необязательными исходными картами.

Короткая демонстрация

Вместо того, чтобы оставаться на теоретической стороне, я хочу, чтобы вы немного попрактиковались со Spider, создав небольшое демонстрационное приложение. Наша цель — использовать как можно больше функций Spider. Кроме того, демо должно быть забавным в использовании, поэтому мы создадим простую игру. Создав этот проект, вы также получите представление об удивительных возможностях наследования Spider.

Основная концепция

Мы создадим простую космическую стрелялку, в которой наш корабль изображен в виде треугольника, а противники представлены в виде кругов. Любое столкновение приведет к уничтожению игрока. Игра будет нарисована с использованием HTML5-холста с контекстом 2D-рисования.

Мы не будем фокусироваться на графике, поскольку наше внимание и заинтересованность должны быть сосредоточены на коде. Мы создадим функцию конструктора GameObject() , которая также будет prototype функций конструктора PlayerShip() и Asteroid() . Объектная game объединит все объекты игры.

Для начала вам нужно скачать несколько ресурсов для нашей игры. Нам требуется хорошее фоновое изображение и звук для воспроизведения в случае столкновения. Игра управляется с помощью клавиш со стрелками на клавиатуре.

Реализация в Spider

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

 fn loadImage(url) { return new Promise(fn (fulfill, reject) { var img = document.createElement('img'); img.src = url; img.onload = () -> { fulfill(img); }; img.onerror = () -> { reject(img); }; }); } 

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

 background.image = await loadImage('http://i.ytimg.com/vi/qbzFSfWwp-w/maxresdefault.jpg'); 

background объект — это особый вид фиктивного игрового объекта. Функция конструктора использует GameObject качестве своего прототипа:

 fn Background(game) extends GameObject(game) { this.draw = () => { if this.image? { var ctx = this.game.ctx; var img = this.image; var w = ctx.canvas.width; var h = ctx.canvas.height; ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, -0.5 * w, -0.5 * h, w, h); } }; } 

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

Игра также содержит другие псевдообъекты. В качестве примера у нас может быть генератор для астероидов. Здесь полезны такие функции, как встроенные циклы и диапазоны. Мы хотим создать астероид только в случайное время и в случайной позиции.

Получение трех случайных чисел (здесь они называются a , b и c ) может быть сделано в одной строке:

 fn AsteroidGenerator(game) extends GameObject(game) { this.move = () => { if Math.random() > 0.95 { var [a, b, c] = [Math.random() for i in [1..3]]; // ... game.items <- new Asteroid(game, location, velocity, radius); } }; } 

Наконец, мы также будем использовать помощников, таких как простой конструктор Point . В качестве примера, мы всегда можем установить значение по умолчанию для любого аргумента. Это уменьшит стандартный код, который проверяет только undefined и применяет значение по умолчанию:

 fn Point(x = 0, y = 0) { this.x = x; this.y = y; // ... this.dist = (that) => { return Math.sqrt(Math.pow(this.x - that.x, 2) + Math.pow(this.y - that.y, 2)); }; } 

Готовое демо-приложение можно посмотреть по адресу html5.florian-rappl.de/Spider/ . Оригинальный исходный код доступен через GitHub .

Ключевые наблюдения

Давайте вспомним особенности, которые мы видели в действии:

  • async и await решить ад обратного вызова
  • Наследование прототипов стало проще
  • Сокращенные имена методов делают код более элегантным
  • Диапазоны велики во многих сценариях
  • Значения по умолчанию полезны
  • Общий код легче читать

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

Вывод

Spider поставляется с некоторыми удобными новыми функциями, а также вносит некоторую последовательность в таблицу. Он охватывает динамическую природу JavaScript, а не борется с ним. В то время как другие языки пытаются противостоять ошибкам, вводя функции времени компиляции, Spider основывается на улучшенной спецификации языка. Много ошибок определенно исчезнет навсегда.

В этой статье мы увидели некоторые из уникальных точек продажи Spider. Мы также создали очень маленький пример приложения, в котором используются новые функции Spider. С Spider возможно гораздо больше, чем я описал в этой статье. По этой причине я рекомендую вам проверить официальную документацию, доступную на spiderlang.org .

Что ты думаешь о Spider? Есть ли у него какие-то привлекательные функции или вы полностью удовлетворены своим текущим рабочим процессом?