SugarJS — Синтаксический сахар для JavaScript



    Что такое SugarJS?


    SugarJS — это open source (лицензия — MIT) библиотека Javascript, который расширяет нативные объекты полезными методами. Она разработана, чтобы быть интуитивным, ненавязчивым инструментом, повышающим выразительность кода, который позволял бы делать больше с меньшим количеством кода и меньше задумываясь над рутиной.

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

    Кратко...

    • Расширяет нативные элементы Javascript полезными, интуитивными методами.
    • Прост для понимания и в использовании.
    • Метод SugarJS не используется при наличии метода в родной реализации браузера.
    • Имеет систему тестирования, имеющую огромный набор тестов.
    • Расширяет возможности работы с датой и временем, обеспечивает их форматирование на нескольких языках (русский есть).
    • Отлично ладит с другими фреймворками и сторонним кодом.
    • Модульность, вы можете включать только нужные пакеты.
    • Полностью совместимый ECMAScript.
    • Заявлена поддержка всех основных браузеров, включая мобильные.
    • Поддерживает Node.js.
    • Имеет хорошую и удобную документацию.


    Заинтересовало? Добро пожаловать под кат.

    Более подробно о работе JS можно почитать в соответствующем разделе документации.
    Пожалуйста, учитывайте, что стандартная поставка SugarJS может не включать некоторые функции. Используйте конфигуратор на сайте для подключения нужных модулей (обратите внимание на значок справа от имени метода в документации).

    Основной функционал SugarJS разделен на семь разделов, я вынесу сюда наиболее интересные на мой взгляд функции:

    String — работа со строками

    'dopamine'.insert('e', 3); // "dopeamine"

    'carve me up!'.from(2); // "rve me up!"

    'carve me up!'.to(2); // "ca"

    'carve me up!'.first(2); // "ca"

    'carve me up!'.last(2); // "p!"

    'jumpy'.has('py');  // true

    'add me!'.add('to ', 4); // "add to me!"

    '[you] escape <me>'.escapeHTML(); // "[you] escape <me>"

    'Добро пожаловать!'.hasCyrillic(); // true

    'welcome'.pad(' ', 1).pad('-', 3); // "--- welcome ---"

    'hell, no!'.parameterize(); // "hell-no"

    'anVzdCBnb3QgZGVjb2RlZA=='.decodeBase64(); // "just got decoded"

    '{n} and {r}'.assign({ n: 'Cheech' }, { r: 'Chong' }); // "Cheech and Chong"


    Number — работа с числами

    (125.425).round(2); // 125.43

    (4235000).format(); // "4,235,000"

    (50).pad(5); //00050;

    (5).daysAfter('Wednesday'); //"Monday, October 8, 2012 00:00"

    (1000000).abbr(); // "1m"

    (75).minutes().duration('ru'); // "1 час"

    (23654).hex(); // "5c66"

    (17).isEven(); // false

    (8).times(function(i) {
      // Эта функция будет вызвана 8 раз. 
    });

    (125.425).round(-2); // 100


    Array — работа с массивами

    ['a','b','c'].forEach(function(el) {
      // Будет вызвано 3 раза, el - текущий элемент массива
    });

    ['a','b','c'].indexOf('c'); // 2

    ['rocksteady','and','bebop'].map('length'); // [10,3,5]

    ['rocksteady','and','bebop'].sortBy('length'); // ["and","bebop","rocksteady"]

    ['rocksteady','and','bebop'].findAll(/o/); // ["rocksteady","bebop"]

    ['rocksteady','and','bebop'].first(1); // ["rocksteady"]

    ['rocksteady','and','bebop'].from(1); // ["and","bebop"]

    ['three','two','one'].groupBy('length'); // {"3":["two","one"],"5":["three"]}

    [1,65,2,77,34].average(); // 35.8

    [1,2].add([2,3]); // [1,2,2,3]

    [1,2].subtract([2,3]); // [1]

    [1,2].intersect([2,3]); // [2]

    [1,2].union([2,3]); // [1,2,3]


    Object — работа с объектами

    Object.extended({ broken: 'wear' }).keys(); // ["broken"]

    Object.extended({ broken: 'wear' }).values(); // ["wear"]

    Object.keys({ broken: 'wear' }); // ["broken"]

    Object.has({ foo: 'bar' }, 'foo'); // true

    Object.merge({a:1},{a:2}, false, function(key, a, b) {
      return a + b; 
    }); // {"a":3}


    Function — работа с функциями

    (function(a) {
      // this = 'wasabi', a = 'bobby'  
    }).bind('wasabi', 'bobby')();

    (function() {
      // задержка выполнения функции 500ms  
    }).delay(500);

    [1,2,3].each(function() {
      // Каждая итерация будет иметь задержку 5ms
    }.lazy(5));

    var fn = (function() {
      // Выполнится только один раз
    }).once();


    RegExp — работа с регулярными выражениями

    RegExp.escape("oh not /b/, aren't those guys gone?"); // "oh not \\/b\\/, aren\\'t those guys gone\\?"

    /broken/.setFlags('gim'); // /broken/gim

    /broken/im.addFlag('g'); // /broken/gim

    /broken/gi.removeFlag('g'); // /broken/i


    Date — работа с датами

    Date.create('2002-06-15'); // "Saturday, June 15, 2002 00:00"

    Date.create('June 15, 2002'); // "Saturday, June 15, 2002 00:00"

    Date.create('today'); // "Wednesday, October 3, 2012 00:00"

    Date.create('2 days ago'); // "Monday, October 1, 2012 09:24"

    Date.create('the last day of 1998'); // "Thursday, December 31, 1998 00:00"

    Date.create('先週金曜日','ja'); // "Friday, September 28, 2012 00:00"

    Date.create('25 минут назад', 'ru'); // "Wednesday, October 3, 2012 08:59"

    Date.create('二十五日', 'zh-CN'); // "Thursday, October 25, 2012 00:00"

    Date.create('il y a une semaine', 'fr'); // "Wednesday, September 26, 2012 09:24"

    Date.create().format('{12hr}:{mm}{tt} on {Weekday}'); // "9:24am on Wednesday"

    Date.create().iso(); // "2012-10-03T03:24:16.831Z"

    Date.create('3200 seconds ago').relative(); // "53 minutes ago"

    Date.create('3200 seconds ago').relative('zh-TW'); // "53分鐘前"

    Date.create('3200 seconds ago').relative('de'); // "vor 53 Minuten"

    Date.create('3200 seconds ago').relative('ko'); // "53분 전"

    Date.create().is('tuesday'); // false

    Date.create().is('the 7th of June'); // false

    Date.create().addMonths(2); // "Monday, December 3, 2012 09:24"


    DateRange — работа с диапазонами дат


    Пример кода


    
    getLatestTweets(function(tweets) {
      var users     = tweets.map('user').unique(),
          total     = users.sum('statuses_count').format(),
          top       = users.max('followers_count'),
          followers = top.followers_count.format(),
          started   = Date.create(top.created_at);
    
      return users.length + ' users with a total of ' + total + ' tweets.\n' +
             top.screen_name + ' is the most popular with ' + followers + ' followers\n' +
             'and started tweeting ' + started.relative() + '.';
    });
    

    Результат:
    20 users with a total of 203,499 tweets.
    Hi_Im_Dopee is the most popular with 744 followers
    and started tweeting 1 year ago.


    Я использую эту библиотеку совместно с jQuery, Knockout, Bootstrap уже больше месяца, и никаких проблем при ее эксплуатации не было.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 67

      +3
      «С удивлением обнаружил, что на Хабре никто не упоминал...» — habrahabr.ru/post/125415/
        +2
        Охтыж, специально ведь в поиске искал…
        0
        Спасибо. Будем знать, где взять
          +6
          Сейчас должны набежать адепты Кроукфорда, истошно вопя, что расширение прототипов — это великое зло))
            0
            В сайте есть даже специальное упоминание 'But Sugar modifies native objects! Isn't that Evil™?' с небольшими разъяснениями.
              +4
              Мое мнение — нигде не мешает, удобно, выразительно — в топку всю эту теорию c расширением, не нравится — используй VanillaJS.
                +1
                Не нужно быть адептом, чтобы понимать, насколько это зло, и почему так делать не стОит. Достаточно взглянуть на историю Protoype.
                  +1
                  Не нужно смотреть на историю prototype. Сейчас при расширении прототипов используются совсем другие техники. Native method first. При отсутствии нативного метода используется polyfill, сделанный в соответствии со спецификацией. Сообщество следит за тем, чтобы код библиотеки обновлялся в соответствии со всеми апдейтами спецификаций. Если появляется нативный метод, которого раньше не было, это тут же учитывается в коде. Так что шанс того, что у вас что-то где-то накроется из-за расширенных прототипов при таком подходе сводится к минимуму, который можно вообще не брать в расчет.
                    +1
                    Вы хотите сказать, что все используемые в библиотеке методы описаны в спецификации?
                    Может случиться такая ситуация в большом проекте, когда кодовая база на клиентской части стала достаточно объёмной и вдруг появляется встроенный метод, поведение которого отличается от поведения, добавляемого библиотекой, отчего сыпется всё приложение. В таком случае необходимо срочно заняться рефакторингом кода в проекте, что может сорвать планы и неблагоприятно повлиять на бюджет…
                      0
                      Да, такое может быть. Это неизбежный процесс. Чтобы идти в ногу со временем, нужно все время что-то обновлять, изменять, рефакторить в соответствии новыми технологиями. Потому что если холить и лелеять код, давным давно написанный и не выделять время и деньги на его усовершенствование, то можно быстро оказаться в ситуации, когда у конкурентов все будет быстрее, отзывчивей, легче в поддержке, менее ресурсоемко и т. д.
                        0
                        Проект необходимо всё время поддерживать, это верно, но в любом более-менее серьёзном проекте необходимо минимизировать риски. В связи с этим стараюсь не использовать расширение встроенных прототипов методами, не описаннными в специффикации.
                          0
                          Чтобы идти в ногу со временем, нужно писать универсальные решения, чтобы не переписывать их на каждый чих браузеростроителей и библиотекописателей. берите пример с ребят, которые писали математический код на Фортране, чьи библиотеки используются спустя 20 лет после написания. Они работают и решают поставленные задачи.
                            0
                            Web — слишком динамическая и нестабильная среда, что сравнивать ее с фортраном. Сегодняшнее бронебойное решение завтра уже будет пережитком прошлого.
                              +1
                              Т.е. вот таки согласны с мыслью, что вот такие библиотеки — они на… не нужны, и через n-дней канут в лету!?

                              Что мешает обрамить логику в функцию? Оставьте примитивы в покое!
                                0
                                Все канет в лету. И jQuery канет в лету и многие другие решения, которые сегодня успешно используются web-сообществом. Но это не значит, что их не нужно использовать для того, чтобы упростить себе жизнь.

                                Что мешает обрамить логику в функцию?

                                Ничего не мешает. Это просто разные подходы. И кто-то готов идти на небольшой риск, для того, чтобы сделать свой код более чистым, посредством неиспользования всяких лишних оберток. Я считаю, что если не подключать одновременно sugar, mootools и prototype, то риск возникновения каких-то проблем от расширенных прототипов меньше процента. Это вполне приемлемо.
                                  0
                                  Вот только библиотеки через одну тянут по несколько зависимостей, в т.ч. prototype, mootools, signals, Zepto и пр.
                            0
                            Вроде как сейчас набирает популярность паттерн неймспейсов, тот же dojo полностью на нем. А расширения прототипов нативных объектов действительно зло, не раз уже сталкивался с этим. Проблемы начинаются от не совместимости библиотек и заканчиваются неожиданным поведением.
                              0
                              Меня убивают неймспейсы. Когда код заполнен конструкциями вида mainNamespace.subNamespace.someObject.someMethod(), на это даже эстетически неприятно смотреть, я молчу уже о количестве писанины.
                      +2
                      А вот и первый адепт Крокфорда — я! И как адепт Крокфорда я со всей ответственностью заявляю, что Крокфорд за разумное расширение прототипов, что он сам демонстрирует собственным кодом: github.com/douglascrockford/JSON-js/blob/master/json2.js#L175

                      А против расширения прототипов адепты Резига! :)
                        –1
                        Замечание про Резига – не в бровь, а в глаз. Столько проблем создает принципиальное нежелание жить в реальности, где кто-то может в старом браузере без defineProperty что-то добавить в прототип Object'а… Хотя казалось-бы разработчики таких фундаментальных библиотек _обязаны_ думать о других вероисповеданиях.
                          –1
                          они никому ничего не обязаны.
                      • UFO just landed and posted this here
                          0
                          Простите, что понимать под шимом?
                          • UFO just landed and posted this here
                        +1
                        Теперь на работе будут приставать, чтобы я использовал это.
                          +13
                          Интересно, почему
                          '{n} and {r}'.assign({ n: 'Cheech' }, { r: 'Chong' }); // "Cheech and Chong"
                          


                          а не
                          '{n} and {r}'.assign({ n: 'Cheech', r: 'Chong' }); // "Cheech and Chong"
                          


                          ?
                            –1
                            Доработайте библиотеку.
                              +1
                              Оба варианта сработают. И второй, собственно, предпочтителен.
                              +8
                              (8).times(function(i) { // Эта функция будет вызвана 8 раз. });

                              Вот и до JS добрались фанаты ruby…
                                0
                                В купе с кофе :)
                                  0
                                  и с питоном.

                                  sugarjs.com/libs/
                                    0
                                    Ну, в купе с динамическим добавлением методов этот приём смотрится не так отвратительно, как если бы это было на Java…
                                    +2
                                    Вы так говорите, как будто это что-то плохое :)
                                    –1
                                    Добавил в избранное ради работ со строками, числами и массивами. Попадаются иногда схожие задачи.
                                      +3
                                      а почему не Undescore documentcloud.github.com/underscore/
                                        0
                                        Тогда уж и underscore.string
                                          0
                                          ну и moment.js к примеру — просто хочется использовать продукты с хорошей поддержкой
                                            0
                                            Что не так с поддержкой у Sugar.js? Только, если можно, без флейма. Я активно принимаю участие в развитие этого чуда. Как по мне, так Andrew Plummer один из самых лучших и адекватных мейнтейнеров, которых я когда-либо встречал.
                                              0
                                              Если честно, то я первый раз слышу о Sugar.js — от этого и такое впечатление, что это новинка и если я услышу о ней еще пару раз — возникнет и доверие.
                                              В коде, как многие, я не копаюсь — я хочу брать и использовать — не думая о том, что через месяц мне придется все переделывать из-за какого-то досадного бага — что встречается например с плагинам для jQuery.
                                              Но спасибо Вам за такой эмоциональный ответ — буду следить за Вашей работой — и попробую поюзать.
                                                0
                                                Ну не такая уж и новинка, на хабре про sugar есть пост годовой давности (http://habrahabr.ru/post/125415/).
                                          +2
                                          Вагон и маленькая тележка причин. Я назову те, которые особенно важны для нас:

                                          1) Синтаксис андерскора высосан из пальца – мой мозг отказывается воспринимать вот это _(_(...) / _(...)). Против этого не помогает даже CoffeeScript.
                                          2) При использовании Coffee-HAML синтаксис один в один руби с ActiveSupport. И это очень-очень хорошо.
                                          3) Гораздо больше функций. Нет этого больного стремления уложить все в 1 килобайт. Спасибо, я лучше уберу одну картинку, но не буду страдать из-за отсутствия флексий (камелизация, плюрализация, етц).

                                          Если хотите развернуто услышать мою позицию: borisstaal.com/post/24270017179/please-use-sugar-js. Но на английском.
                                        0
                                        Довольно спорная либа. Чтото есть чего то нет. По сути выжимка из набора библиотек, таких как underscorejs и datejs. Хотя может быт весьма полезна.
                                          0
                                          'Добро пожаловать!'.hasCyrillic(); // true
                                          Серьёзно? И на каждый язык так?
                                            0
                                            Methods:

                                            isArabic
                                            isCyrillic
                                            isGreek
                                            isHangul
                                            isHan
                                            isKanji
                                            isHebrew
                                            isHiragana
                                            isKana
                                            isKatakana
                                            isKatakana
                                            isThai
                                            isDevanagari
                                              +8
                                              Какой ад.
                                                0
                                                У разработчиков библиотеки свой взгляд на паттерны проектирования :)
                                                  +1
                                                  кому удобно то юзает, кому не — не юзает. Колхоз — дело добровольное.
                                                  +1
                                                  Они беспощадны
                                                  string.prototype.isLocale = function(locale) { 
                                                     if (('is' + locale) in this && this['is' + locale] instanceOf Function) 
                                                        return this['is' + locale]();
                                                     return false
                                                  }
                                                  
                                                    0
                                                    isArmenian, isOriya, isBengali, isJavanese, isLao, isSinhala, isCherokee… где же всё это?
                                                      0
                                                      Не удержусь чтобы не процетировать автора:

                                                      @_inossidabile lol, isCherokee actually used to exist!! I took it out because come on right? I can add again when a Cherokee complains :) :)
                                                        +1
                                                        И клингонский не забудьте
                                                    +2
                                                    Да, прекрасная библиотека. Читал код.

                                                    // Вообще говоря, у меня ко многим JS-библиотекам интересный подход — вместо документации мне нравится читать код).
                                                      0
                                                      Читая код трудно оставаться беспристрастным, лучше читать сначала интерфейсы, а потом уже код. Тов. Макконнелл в «Совершенном коде» описывал проблему, из-за которой не стоит смотреть код сторонних библиотек. Точно не перескажу, но суть в том, что это как читтинг при написании своего кода, который использует чужой. Зная что скрывается за интерфейсом, можно плддаться соблазну использовать недокументируемые возможности. Я, честно сказать, тоже люблю читать исходники, но стараюсь ориентироваться по юзергайдам к использованию.
                                                      0
                                                      Хорошая, в некоторых местах библиотека, но такого полезного метода как ES6 String.prototype.repeat нету :(
                                                        0
                                                        Добавляйте ишью, пожалуйста. Сделаем.
                                                          0
                                                          Я вам сделаю pull request
                                                            +1
                                                            Низкий Вам поклон :)
                                                              0
                                                              Запулил быструю версию. Торопился (работы много), поэтому не выделял в отдельную ветку
                                                            0
                                                            Есть в либе, что на github. Только медленная реализация
                                                              0
                                                              Опять-же, ставьте ишью, все обсудим, поправим. Ничего идеального не бывает, но основной мейнтейнер там нереально адекватный. Так что в случае шугара к этому вполне реально стремиться.
                                                          0
                                                          с Якартами конфликтует)
                                                            +2
                                                            Касательно работы с датами:
                                                            вот почему каждая js-обертка стремится выдумать свои спецификаторы в формате?
                                                            date.js, moment.js теперь еще и sugar.js — формат нигде не совместим!
                                                            0
                                                            Не вижу (по примерам) разницы между функциями для работы со строками insert/add и to/first
                                                              0
                                                              Javascript чем-то неуловимо напоминает С++ в его худших чертах. Наверное, отсутствием стандартных реализаций общепринятых вещей…

                                                              Библиотека из серии «я бы сам такое написал, если бы мне позволили исать фреймворки без обсуждения с командой, а тут, слава Богу, есть внешнее решение, за которое мы не должны нести ответственностть в части работоспособности и тестирования».
                                                                0
                                                                … писать фреймворки…

                                                              Only users with full accounts can post comments. Log in, please.