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

Все мы хоть раз слышали о jQuery. С некоторых пор я буквально влюбился в это творение, как и в сам JavaScript. За моей спиной очень много строк кода. Рабочего, любительского, простого фонарного кода. С недавних пор я начал изучать структуру всеми любимой jQuery и пришёл к выводу, что это ничто иное, как шедевр.

Почему здесь эта статья?


На моём счету немало разработок, которыми я пытался упростить себе процесс программирования, многие из них были jQuery-like. Но увы, разработка и поддержка останавливалась и забрасывалась в силу моей занятости и они так и не вышли за пределы моего жесткого диска.

Некоторое время назад мне, уже будучи неплохо ознакомленному со структурой jQuery, пришла в голову мысль: что если сделать конструктор, где мы сами будем указывать функцию, которая будет подбирать для нас необходимые данные и собирать их в объект jQuery? Нет, здесь нет никакой речи о селекторном разборе веб-страниц, об анимациях, ajax и прочих плюшках и вкусностях jQuery. Я подумал: что если наша библиотека будет подстраиваться под требования программиста (будь то перебор банальных чисел, строк, объектов с данными или даже файлов) вне зависимости от платформы, на которой запущен данный код?

Так пришла идея собрать этот небольшой фреймворк.

Давайте разберемся, что к чему.

jQuery Builder — это микрофреймворк, предназначенный для создания jQuery-like библиотек для манипуляции различными данными. На данный момент я пока решил унаследовать класс jQuery от родного js-массива, но в будущем это будет исключено и будут созданы свои аналоги стандартных методов.

Приведу пару простых примеров:

Пример №1. Предположим, у нас есть массив данных, из которого нам нужно сформировать jQuery-объект с необходимыми методами. Пусть это будут банальные числа.

Код
// Наши числа
var numbers = [4, 8, 15, 16, 23, 42, 108];

// Сам конструктор
var builder = new JQueryBuilder(function (selector) {
	// Перебираем числа
	for(var i = 0; i < numbers.length; i++) {
		// Проверяем селектор
		switch (selector) {
			// Если мы ищем чётные числа
			case 'even' :
				// ... и число подходит под требования
				if (numbers[i] % 2 === 0) {
					// Добавляем его в выборку
					this.push(numbers[i]);
				}
				break;
			// Если мы ищем нечётные числа
			case 'odd' :
				// ... и число подходит под требования
				if (numbers[i] % 2 !== 0) {
					// Добавляем его в выборку
					this.push(numbers[i]);
				}
				break;
		}
	}
});


Поле jQuery содержит в себе необходимый нам объект (если быть точнее, это функция), где будет содержаться наша выборка и необходимые методы (из jQuery.fn).

Итак, мы только что выполнили первую основную задачу — мы сформировали наш конструктор. Он представляет из себя функцию, в которой исполняется цикл, перебирающий наш массив. При соответствии числа нашим требованиям число будет добавлено в выборку.

Теперь создадим новый метод. Всё делается точно так же как в настоящем jQuery — через объект fn.

Код
var $ = builder.jQuery;
$.fn.add = function (value) {
	var self = this;
	return this.each(function (i) {
		self[i] += value;
	});
};
var result = $('even').add(5);
console.log(result); // [9, 13, 21, 47, 113]


Ожидаю в комментариях эту картинку, однако здесь всё гораздо приятнее. Данная библиотека, по моему мнению, может оказаться полезной для быстрого нахождения решения частых (и не только) задач касательно массивов.

Пример №2. Теперь проделаем что-то подобное со строками.

Код
var $ = jQueryBuilder.fromArray().jQuery;
$.fn.extend({
	reverse: function () {
		var self = this;
		return this.each(function (i) {
			var result = '';
			for(var x = self[i].length - 1; x >= 0 ; x--) {
				result += self[i][x];
			}
			self[i] = result;
		});
	},
	upper: function () {
		var self = this;
		return this.each(function (i) {
			self[i] = this.toUpperCase();
		});
	},
	lower: function () {
		var self = this;
		return this.each(function (i) {
			self[i] = this.toLowerCase();
		});
	}
});
var result = $('abcde', 'xyZ', 'HAAR')
		.reverse()
		.lower()
	;

console.log(result); // ["edcba", "zyx", "raah"]


На мой взгляд, всё очень просто и понятно. В следующей статье я расскажу, как применил эту библиотеку к Adobe After Effects, в котором есть возможность писать скрипты на Javascript. Получился эдакий jQuery для перебора и управления слоями в композиции. В ближайшем будуем планирую изучить скриптинг Фотошопа и разработать аналог для него.

Репозиторий тут. Обещаю постепенно дополнять примерами.

Спасибо за внимание.

UPD.
Сейчас плотно изучаю Coffeescript. Планирую переписать Builder на него.

Комментарии (104)


  1. creage
    02.04.2015 12:09

    Коменты на гитхабе поправить бы


    1. Serabas Автор
      02.04.2015 12:12
      -1

      Да, там кодировка слетела. Как будет время — обязательно


      1. Serabas Автор
        03.04.2015 01:33

        Беспощадные минусаторы :(
        Я репозиторий развернул, можно сказать, на коленке, предварительно прогнав через него несколько примеров, используя код, который написал с ~полгода назад.
        Вот, рассказал об идее на Хабре, пока у людей впечатлений мало. Да, в этом моя вина — не достаточно ёмко.
        За ближайшую пару недель постараюсь найти время и довести всё до ума. Моей задачей несколько дней назад была демонстрация самой идеи. Разработка, поддержка и натирание напильником доработка — всё в будущем, ближайшем, конечно же.


  1. maximw
    02.04.2015 12:23

    В первом блоке кода case 'even': — в обоих случаях.


    1. Serabas Автор
      02.04.2015 12:26

      Исправил. Спасибо. Писалось глубокой ночью.)


  1. Encircled
    02.04.2015 12:34
    +4

    JQuery хороший инструмент, но…

    это ничто иное, как шедевр

    Весьма спорное утверждение, если честно :)


    1. Serabas Автор
      02.04.2015 12:43

      Да, утрирую малость. Но всё же, поработав с jQuery несколько лет и изучив его структуру и философию, я всё же больше люблю его, чем безразличен =)


    1. nazarpc
      02.04.2015 13:45
      +4

      На самом деле если зайти в обсуждения на GitHub — там огромное количество комментариев списывается чтобы изменить 5 строчек. Реально нигде такого тщательного обсуждение каждой детали не видел, так что решения, которые там используются почти что на 100% настолько оптимальны и продуманы, на сколько это возможно. В своем роде однозначно шедевр, альтернативы ему по удобству и распространенности нет.


      1. Serabas Автор
        02.04.2015 14:28

        Write Less Do More
        :)


      1. Encircled
        02.04.2015 21:35

        решения, которые там используются почти что на 100% настолько оптимальны и продуманы, на сколько это возможно

        И еще одно весьма спорное утверждение. Не хочется разводить холивар если честно, но инструмент, который имеет настолько большой функционал, с большой вероятностью не может быть «на 100% оптимальным» в частных случаях.

        Я ни в коем случае не говорю, что jQuery плох. Просто странно видеть такие эпитеты об инструменте. А жить без jQuery надо хотя бы иногда, это полезно.


      1. oWeRQ
        03.04.2015 13:40

        Оптимальны только с точки зрения кода(опять же спорное), многие, банальные с виду, функции выполняют столько «незаметной» работы, что шерсть дыбом встает.

        Значительная часть функционала чаще всего не используется, по 2-м причинам: по не знанию и по опыту. Не припомню когда была реальная необходимость использования расширенных селекторов, да и вообще сложных селекторов, 95% — выбрать класс.

        Часть фукционала становится стандартом, например, Promises, fetch, bind, querySelector, classList, dataset, css для анимации etc, единственное, что вряд ли станет стандартом — цепочки вызовов.

        Крайне познавательная презентация на тему:
        speakerdeck.com/addyosmani/devtools-state-of-the-union-2015

        P. S. В неумелых руках, jQuery — дробовик для отстреливания обоих ног одновременно.


  1. gagoman
    02.04.2015 12:48
    +2

    Почему вы не используете обычные средства языка для манипуляций над коллекциями? Если их не хватает, есть lodash/lazyjs/whatever.

    К примеру, ваш код на ES6:

    // First sample
    
    const isEven = n => n % 2 === 0;
    
    const numbers = [4, 8, 15, 16, 23, 42, 108];
    
    numbers.filter(isEven).map(n => n + 5); // [9, 13, 21, 47, 113]
    
    // Second sample
    
    const toLower = s => s.toLowerCase();
    const reverse = s => s.split('').reverse().join(''); // TODO: look for Unicode-aware reverse
    
    const strings = ['abcde', 'xyZ', 'HAAR'];
    
    strings.map(toLower).map(reverse); // ["edcba", "zyx", "raah"]
    


    1. Serabas Автор
      02.04.2015 13:02

      Я унаследовал jQuery (который получается на выходе) от стандартного массива.
      И да, цель статьи, да и вообще самой библиотеки — показать, как устроен jQuery и что с этим можно сделать. По поводу использования\не использования чего-либо в коде — прошу всех в репозиторий.


    1. nazarpc
      02.04.2015 13:47
      -5

      ES6? А не CoffeeScript случайно?


      1. gagoman
        02.04.2015 13:57
        +4

        1. nazarpc
          02.04.2015 14:06
          +1

          Спасибо


      1. Fesor
        02.04.2015 15:17
        +3

        Вас стрелочные функции смутили?


        1. nazarpc
          02.04.2015 15:18
          +2

          Ну да


  1. Serabas Автор
    02.04.2015 13:20

    Вопрос к знатокам.
    Как-то я пытался разработать что-то подобное на Java. Но выглядело это несколько иначе. Если в моём слуачае на JS мы создаём instance конструктора jQueryBuilder с указанием функции-конструктора как аргумент, то на Java это был родительский класс со прописанными стандартными методами (each, map, etc), от которого наследовался класс с необходимым программисту функционалом. Есть ли смысл реализовывать то же самое на JS?


    1. Fesor
      02.04.2015 15:19

      Объектная модель другая. Отсюда и различия в подходах.


      1. Serabas Автор
        02.04.2015 19:06

        Согласен. Спасибо


  1. hell0w0rd
    02.04.2015 16:35
    +2

    Странно в 2015 году восхваление jquery, если честно. Хочется наоборот, чтобы библиотека отправилась быстрее на покой, а все плагины вокруг были переписаны нативно.


    1. dom1n1k
      02.04.2015 16:56
      +1

      Переписать нативно можно. Но в них будет куча дублирующегося кода.


      1. hell0w0rd
        02.04.2015 20:31

        Сейчас и в jquery компонентах куча повторяющегося кода. Полифилы новых функций, целые либы, обычно они достаточно маленькие, но все равно.
        В node мире все становится лучше — компоненты стараются переиспользовать другие компоненты, вот того же хотелось бы и в браузерном js.


        1. dom1n1k
          02.04.2015 20:52

          Кому как.
          Я понимаю логичность подхода node, но на повседневной практике мне это было бы неудобно.
          Скачал и подключил, и не сидишь и не думаешь — сколько там неявных зависимостей?


          1. hell0w0rd
            02.04.2015 22:19

            Какой-то вы бред говорите. Когда скачиваешь билд библиотеки как раз не понятно что туда входит. А если используешь npm/bower — сразу видно зависимости.


            1. dom1n1k
              02.04.2015 23:46

              Угу, а у тех зависимостей свои зависимости и так далее…
              В случае с jQ-подобным пакетом обычному пользователю, по большому счету, и не интересно что там внутри. Оно точно работает и это главное.


              1. Fesor
                02.04.2015 23:50
                +1

                В случае с node-зависимостями обычному пользователю тоже не особо есть дело что юзают либы, от которых зависит его проект. В этом собственно весь смысл менеджеров пакетов, скрывать от пользователя библиотеки ее зависимости. Вы же не используете API зависимостей, а только через API библиотеки которую используете.


                1. dom1n1k
                  03.04.2015 00:01
                  +1

                  Сама система в целом как бы логична, но на практике (это мое имхо) её довели до абсурда. Поясню на примере.

                  Захожу я на npmjs.com, ввожу в поиск color и получаю 3,7к пакетов. Для любого другого неспицифичного ключевика результаты будут аналогичны. Причем называются они в большинстве незатейливо — утрированно говоря, я вижу список названий color-foo, color-bar, color-foobar, color-bla, color-blabla и т.д. Большинство выполняет какую-то очень маленькую и узкую функцию (о да, я знаю, linux-way), многие их них переплетены в обширный граф зависимостей.

                  Как я должен найти в них то, что мне нужно и подойдет? При ближайшем рассмотрении большинство оказывается либо узкоспецифичным, либо не совсем то что нужно, либо кривая реализация и тд и тп. Я предпочел бы не копаться в этом муравейнике, а увидеть вместо 3,7к ну скажем 30-50-100 библиотек, но каждая из них была бы каким-то более-менее законченным решением.


                  1. Fesor
                    03.04.2015 00:10

                    Захожу, ввожу «color», вижу все что может придти в голову на первой же странице. Если по названию сложно определить что делает модуль — читаю описание.

                    Надо смешивать цвета — не вопрос, вот модуль. Надо конвертить из RGB в HSV и обратно — не вопрос, вот она, четвертая в третьем столбце…

                    Короче эта проблема надумана. В случае с NPM меня напрягает только то, что туда пихают сейчас все что нужно и не нужно. Скажем зачем jQuery та же в npm мне не понятно. Для работы с DOM на стороне сервера? Возможно, ок. Но зачем туда запихнули тот же Angular? По запросу angular находит over 2К модулей. Из них на бэкэнде хорошо если сотня другая применима. А аргументируют это использованием таких штук как browserify.

                    В целом все это вопрос культуры разработки.


                    1. dom1n1k
                      03.04.2015 00:16

                      > вижу все что может придти в голову на первой же странице

                      Это потому что не углублялись в тему :) Реально там очень много кривоватых и неподходящих велосипедов.


                      1. Fesor
                        03.04.2015 01:38

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


                    1. hell0w0rd
                      03.04.2015 11:20

                      А я наоборот считаю, что все фронтендские модули хорошо запихнуть в npm. И да, это гораздо удобнее, чем bower.


                      1. Serabas Автор
                        03.04.2015 11:29

                        Однозначно плюсую


                      1. Fesor
                        03.04.2015 12:38

                        А вот интересно, почему? Тип один менеджер пакетов для всего? Ну ставить набор шрифтов и стилей через npm мне религия не позволяет…


                        1. hell0w0rd
                          03.04.2015 12:53
                          +1

                          Если использовать webpack — это очень удобно. А потом есть куча модулей, которые можно использовать как на клиенте, так и на сервере, зачем тогда остальные разделять?
                          npm хорошо бы допилить напилником, чтобы main директива была более кастомная и будет просто замечательно.
                          Есть еще допустим apm — пакетный менеджер для Atom. Все пакеты под него публикуются в npm, и они вполне могут использовать jquery (и кстати используют), или иконки.
                          Фактически помимо серверной части и браузерной есть промежуточная, для nw.js/atom-shell/native-script/react-native и тому подобных, которые имеют доступ как к node-api (io) так и браузерному (dom). Для такого использования лучше npm ничего быть не может.


                    1. Mithgol
                      05.04.2015 10:42

                      Скажем, зачем jQuery та же в npm, мне не понятно. Для работы с DOM на стороне сервера? Возможно, ок.
                      Вы (как мне показалось) неявно предполагаете, что npm нужен только для того кода, который затем станет работать на стороне сервера.

                      Между тем это не так, потому что есть другие, ничуть не менее полезные, способы применения его.

                      Можно (например, посредством Browserify) собирать из npm-модулей код для браузера.

                      Также можно (например, посредством nw.js или Atom Shell) запускать код Node в качестве приложений, имеющих GUI (графический интерфейс пользователя) на десктопах.


    1. Fesor
      02.04.2015 17:29

      WebComponents грядут…


      1. hell0w0rd
        02.04.2015 20:28
        +1

        Да уже есть polymer, angular, react. Не знаю как polymer, но найти под angular кучу необходимых компонентов практически не реально. Банально большинство wysiwyg требуют jquery. Или select2-подобных плагинов.


        1. Fesor
          02.04.2015 22:22

          Все довольно просто объясняется. У большинства просто нет необходимости избавляться от jQuery. Там где эта необходимость появляется — избавляются. Я уже давно не подключал jQuery из-за каких-то зависимостей, хотя было такое дело.


          1. hell0w0rd
            03.04.2015 11:18

            В админке не получается от нее избавиться, хотя в админке это не так существенно.


            1. Fesor
              03.04.2015 12:39

              Хз, на последнем проекте мне для админки jQuery не понадобилась. А в мобильных апах я уже давно не видел потребностей в jQuery.


    1. Serabas Автор
      03.04.2015 01:42

      Я смотрю, утрированное понятие «шедевр» привлекло внимание читателей больше, чем сама статья)
      Ну, нет же, мне просто нравится jQuery, какой он есть сейчас.

      ИМХО на покой jQuery отправится ещё не скоро (к сожалению или к счастью — не знаю).
      С развитием языка Javascript и внедрением его всеми-кому-не-лень во-все-какие-можно-дыры (Node, Adobe, Google Drive, Unity? и пр.) становится как-то не по себе — а что, собсна будет дальше? Мне, как человеку, знакомому с языком «выше среднего», весьма интересен ответ на этот вопрос.
      По поводу нативности — очень сомневаюсь. Хотя догадки возникали ещё года 3 назад.


      1. Fesor
        03.04.2015 08:37
        +1

        если не нужно суппортить IE хотя бы до 11-ой версии то уже можно выкидывать jQuery в пользу какой-нибудь крайне легковесной библиотечки. Я не могу придумать чем jQuery может быть полезен сегодня, если речь не идет о IE и старых версиях каких-нибудь сафари и фаерфоксов.

        Вообще имеет смысл сделать простенькую библиотечку на подобии ангуляровского jqLite и делать проекты с зависимостью от нее. А если подключить jQuery то имплементация просто подменяется. И тогда все счастливы.


        1. Serabas Автор
          03.04.2015 08:46

          Я не могу придумать чем jQuery может быть полезен сегодня, если речь не идет о IE и старых версиях каких-нибудь сафари и фаерфоксов.


          Как насчёт того, что я описал в статье?


          1. Fesor
            03.04.2015 09:00
            +1

            Делать перебор строк/чисел/etc плагинами для jQuery? Плюшки для работы с ajax? так есть отдельные библиотеки которые получше подходят для этих целей (так же в фреймворках частенько идут свои имплементации). Вместо какого-то объекта fn в который пихаются какие-то плагины — web components и IoC.


            1. Serabas Автор
              03.04.2015 09:11

              Примеры с числами и строками — лишь пример для подачи идеи.
              В следующей статье я буду перебирать слои в Adobe After Effects и манипулировать ими — как результат. А затем — слои Фотошопа (если разберусь с ними, конечно). Ещё была практика внедрения Builder'а в Google Drive для работы с файлами на моём Диске. Получалось достаточно просто, но в некоторых случаях помогало очень. К примеру, если мне нужно найти определенную выборку файлов по хитрозакрученным критериям и что-нибудь с ними сделать (банальный пример — удалить).


              1. Fesor
                03.04.2015 10:40
                +1

                Мне не нравится ваш пример со строками тем, что эти методы можно было бы просто объявить методами прототипа String и радоваться жизни.

                $('foo', 'bar').reverse()
                
                //vs 
                
                ['foo', 'bar'].map((word) => {
                    return word.reverse();
                });
                


                Я предпочту увидеть в коде проекта именно второй вариант, потому что он явный, без магии и прочей чуши. А методы аля reverse и т.д. стоит пихать в прототип объекта.


                1. Serabas Автор
                  03.04.2015 11:20
                  -1

                  Исходя из изученного мной за всё время работы с JS, я убедился, что расширение прототипов — не есть хорошо. По многим причинам. Хотя сам иногда этим балуюсь — в текущем положении JS не всё хорошо со стандартным набором функционала.

                  Однако же, мой пример из статьи — это далеко не .map() или что-то ещё. Представьте, что у вас есть большой набор каких-то данных и вам нужно отобрать из него выборку по определенным критериям. Что мы делаем на «чистом» JS? мы отбираем их через .filter() c функцией как аргумент. Если же нам нужно вызывать тот же самый .filter() несколько раз в разных местах, мы сохраняем функцию-аргумент в переменную и вызываем в нескольких местах, где она доступна.

                  Окей, теперь мой случай — я пишу функцию единожды, сохраняю её в объект jQuery.expr с нужным мне ключом (пусть это будет банальный odd из примера в статье) и вызываю что-то вроде jQuery('odd') в любом месте, где мне это будет необходимо (конечно же, в том контексте, где доступен jQuery, в большинстве случаев он глобален). Если же мне где-то нужно вызывать другую функцию, я делаю то же самое, ну а если мне в одном месте понадобится какая-то особая логика отбора, я вместо строки передаю туда функцию, которая отберёт мне мои данные. Предполагается, что программист научит Builder понимать как можно больше типов селекторов.

                  Приведу пример из моей разработки для Adobe After Effects (статья о которой скоро будет на Хабре):

                      jQuery(':active') // выбираем только те слои, которые отмечены, как активные (":" - управляющий символ, говорящий о том, что сейчас нужно будет найти функцию из jQuery.expr), active - ключ в jQuery.expr, по которому находится отбирающая функция
                      jQuery(1) // Получаем один слой, индекс которого равен единице
                      jQuery('Layer 1') // Получаем слои, имя которых равняется Layer 1
                      jQuery(/TextLayer \d+/) // Получаем слои, имя которых соответствует регулярному выражению
                      jQuery([1, 'Layer 1', 'Layer 2']) // Получаем слои, которые подходят под условия каждого элемента массива.
                      // и так вплоть до предела нашей фантазии
                  


                  И всё почти точно так же, как в браузерном jQuery. Можно к примеру сделать какой-нибудь парсер расширенных селекторов.
                  В каждой из этих выборок лежит набор предопределённых программистом методов, с помощью которых он может управлять всей выборкой без лишних движений.


                  1. hell0w0rd
                    03.04.2015 11:28
                    +4

                    jQuery — god object. И похоже вам это нравится, потому что вы хотите на него навесить еще больше ответственности.
                    Если мне нужно работать математическими преобразованиями — я напишу себе такую библиотеку, или возьму существующую. Со слоями в AE — аналогично. Это отдельный сервис, никак не связанный с jquery.

                    А по поводу прототипов — угу, не хорошо, но в качестве исключения для стандартных методов, вроде map, filter, trim и тд норм. Кому совсем припекает — lodash, хотя на мой взгляд стандартную функциональность лучше просто оборачивать в полифил.


                    1. Serabas Автор
                      03.04.2015 11:38

                      Это отдельный сервис, никак не связанный с jquery.

                      Осмелюсь поправить Вас — Это отдельный сервис, связанный с jQuery уважаемого Джона Резига структурой и философией, но нацеленный на более широкие нужды.

                      хотя на мой взгляд стандартную функциональность лучше просто оборачивать в полифил.

                      Эх, если бы Javascript поддерживал методы расширения, как в C# или мета-классы, как в Groovy, которые не засоряли бы стандартные прототипы, но вызывались бы как функции прототипа, было бы очень здорово. В ES6, случаем, не намечается чего-то подобного?


                      1. hell0w0rd
                        03.04.2015 12:11
                        +1

                        Поправляйте, или нет, вы ставите в жесткую зависимость от jquery, достаточно серьезную библиотеку. А я изначально написал — мечтаю о том дне, когда это закончится. На jquery свет клином не сошелся, стандартный js куда богаче, чем раньше, есть полифилы и куча маленьких модулей, отлично решающих свою задачу. jQuery тут не нужен.

                        if (typeof Array.prototype.forEach === 'undefined') {
                            Array.prototype.forEach = function() {...};
                        }
                        

                        Чем такой метод не подходит?


                        1. Serabas Автор
                          03.04.2015 12:17

                          Любая библиотека ставит в зависимость от себя.
                          Мне одно не понятно, почему Вы так «мечтаете о том дне, когда это закончится»? Лишние зависимости? Отсутствие нативной поддержки? Или что Вам, уважаемый, спать спокойно не даёт?)


                          1. hell0w0rd
                            03.04.2015 12:22

                            Библиотека — да. Если вы пишите библиотеку для работы с AE, а я захочу ее использовать — мне совсем не весело будет за вашей библиотекой еще и jquery тащить, ради его API.
                            Вообще не понимаю, при чем тут jquery может быть, давайте в pdf.js jquery добавим


                            1. Serabas Автор
                              03.04.2015 12:58

                              Господи, кажется я совсем-совсем плохо написал статью.
                              Никакого оригинального jQuery, который весит 100k (а то и больше) тащить с собой не нужно.

                              jQuery Builder — это микрофреймворк, предназначенный для создания jQuery-like библиотек для манипуляции различными данными.


                              В общем кто-то из нас не понял другого.


                              1. Fesor
                                03.04.2015 13:10

                                Смущает то что jQuery нужен для манипуляции DOM. Для манипуляции с данными есть underscore/lodash с теми же плюшками что вы описали. Но о них в статье упоминаний нет.


                                1. Serabas Автор
                                  03.04.2015 13:24

                                  Каюсь, не ознакомлен близко с ними. На выходных почитаю. Спасибо.


  1. hell0w0rd
    02.04.2015 22:21
    +3

    Сейчас плотно изучаю Coffeescript. Планирую переписать Builder на него.

    Не надо. Лучше посмотрите в сторону ES2015 babeljs.io.


    1. benedikt
      03.04.2015 05:25

      И чем же CoffeeScript хуже ES2015 babeljs.io?


      1. Fesor
        03.04.2015 08:34
        +2

        Тем что кофе это кофе а ES2015 это стандарт, где в принципе есть все что и в кофе только больше. Как минимум ради модулей, промисов и кучи других вещей стоит его использовать.

        Меня к слову дико напрягает когда какая-то сторонняя библиотека пишется на кофескриптах вместо ES. Даже на TypeScript норм ибо это все тот же ESnext + плюшки. А так… шанс того что я буду пользоваться библиотекой или контрибьютить в нее резко понижается.


        1. hell0w0rd
          03.04.2015 10:44
          +1

          Промисы можно и с coffee юзать, все что делает babel в плане стандартной библиотеки — подрубает core-js, а это набор полифилов, который можно подключить и в coffee.
          А в целом — полностью согласен.


        1. benedikt
          03.04.2015 11:54
          -4

          Тем что кофе это кофе а ES2015 это стандарт

          CoffeeScript добавляет синтаксический сахар в духе Ruby, Python, Haskell и Erlang. И люди, которые используют сейчас CoffeeScript навряд ли будут использовать стандарт ES2015, даже тогда, когда он станет стандартом. Почему? Опять же из-за синтаксического сахара, который по душе программистам Ruby, Python, Haskell и Erlang.

          где в принципе есть все что и в кофе только больше

          Если в каком-то препроцессоре есть все что и в кофе, это еще не достаточный аргумент для того, чтобы отказываться от CoffeeScript.

          Как минимум ради модулей, промисов и кучи других вещей стоит его использовать.

          Есть куча библиотек, которые дают возможность использовать поведение промисов и модулей, и эти библиотеки можно спокойно использовать вместе с CoffeeScript.

          Меня к слову дико напрягает когда какая-то сторонняя библиотека пишется на кофескриптах вместо ES

          Меня тоже к слову дико напрягает когда какая-то сторонняя библиотека пишется на ES вместо кофескриптах. Но приходится с этим мириться и жить дальше.

          А так… шанс того что я буду пользоваться библиотекой или контрибьютить в нее резко понижается.

          Я думаю автор библиотеки не умрет от горя, если вы не станете пользоваться его библиотекой. Вы можете написать свою например или найти альтернативу.


          1. hell0w0rd
            03.04.2015 12:19
            +1

            Вы походу фанатик coffee и не хотите ничего видить вокруг. Язык развивается, coffee стоит на месте. Единственное достоинство — синтаксис.


            1. benedikt
              03.04.2015 12:49

              а какие есть минусы?


              1. rock
                03.04.2015 13:24

                Вот же, блин, развели кофе-срач. Я люблю кофе. Кофе — хороший язык. Вот только для своего времени. Вы серьёзно считаете, что во время, когда протокол итераторов станет стандартом для работы с коллекциями или async / await — стандартом при работе с асинхронными функциями, кому-то будет дело до кофе, основанного на ES3 и успешно игнорирующего нововведения в ECMAScript? Сахарный язык в стиле кофе, основанный на ES6+, нужен, но это будет уже не кофе. В своё время казалось, что приемником кофе станет LiveScript, но и он прекратил активное развитие.


                1. benedikt
                  03.04.2015 13:53

                  основанного на ES3 и успешно игнорирующего нововведения в ECMAScript

                  Почему разработчики должны реагировать на нововведения в ECMAScript если эти нововведения еще не вступили в силу? Когда придет время, все будет реализовано.


                  1. rock
                    03.04.2015 14:03

                    Когда придет время, все будет реализовано.

                    Ага. Также, как и синтаксис геттеров / сеттеров, «вступивший в силу» 6 с лишним лет назад :D


                    1. benedikt
                      03.04.2015 14:45
                      -3

                      Я если честно не в курсе, что там было с синтаксисом геттеров / сеттеров, «вступивший в силу» 6 с лишним лет.

                      Но по факту имеем:

                      на этот текст:

                      Сейчас плотно изучаю Coffeescript. Планирую переписать Builder на него.

                      уважаемый пользователь hell0w0rd ответил этим текстом:
                      Не надо. Лучше посмотрите в сторону ES2015 babeljs.io.


                      На мой вопрос «И чем же CoffeeScript хуже ES2015 babeljs.io?» — я никаких внятных аргументов не получил!

                      Далее я задал вопрос «какие есть минусы у CoffeeScript?» — я опять никаких внятных аргументов не получил!

                      Ваш аргумент, это то что у CoffeeScript нет будущего. Т.е. вы предсказываете будущее. И я должен вам поверить. Почему я должен вам поверить? Сами разработчики Кофескрипта писали когда-нибудь, что они прекращают развитие проекта?


                      1. rock
                        03.04.2015 15:30
                        +1

                        Т.е. вы предсказываете будущее.

                        Да. Я предсказываю будущее. У кофе в его текущей форме его нет. Верить мне или нет — дело ваше. Почему? Потому как, судя по changelog, выпуск релизов кофе сейчас раз в полгода, а изменений в них — что в babel за пару дней. И это при огромном числе открытых issue, на них ссылку вам привели ниже. Мертвецы тоже не сообщают, что они умерли, просто лежат и воняют.

                        На мой вопрос «И чем же CoffeeScript хуже ES2015 babeljs.io?» — я никаких внятных аргументов не получил!

                        На этот вопрос вам ответили. Но, судя по тому, что вы не в курсе, что там с геттерами и сеттерами — о внятности аргументов судить не вам — лучше подучите основы и кофе, и js. Про babel я не заикался, но раз уж втянули — повторюсь:

                        • Babel — trasnpiler, содержащий в себе набор трансформеров. Хотите ES7 -> ES3 — пожалуйста, ES7 -> ES6 — тоже, да и какую одиночную фичу преобразовать можно. Все его текущие возможности основаны на стандарте языка, со временем они будут доступны нативно и соответствующие трансформеры можно будет выключить.
                        • Кофе преобразует свой синтаксис в ES3 и только. Кофе не поддерживает возможности, добавленные после IE6.


                        1. benedikt
                          03.04.2015 16:56
                          -2

                          Сколько по вашему должно быть релизов в год, чтобы проект считался что он развивается? Проект существует очень давно и уже достаточно состоявшийся. Cейчас раз в полгода — мне лично всего хватает. Babel проект относительно новый и поэтому у него активность выше.

                          Огромное число открытых issue есть во многих проектах, это еще ни о чем не говорит!

                          У проекта большое сообщество и большое количество контрибьюторов, они все люди, а не мертвецы как вы утверждаете! И если развитие проекта прекратиться, то об этом объявят.

                          На мой вопрос «И чем же CoffeeScript хуже ES2015 babeljs.io?» мне ответить-то ответили, но не убедили! Слишком не убедительно.

                          Кофе не поддерживает возможности, добавленные после IE6.
                          Если сейчас пока не поддерживает это еще не значит, что не будет поддерживать в будущем.
                          Одна из причин почему люди используют сейчас CoffeeScript это синтаксического сахар и даже тогда, когда текущие возможности основанные на стандарте языка ES6 будут доступны нативно и соответствующие трансформеры можно будет выключить. Люди все равно будут использовать CoffeeScript.


      1. hell0w0rd
        03.04.2015 10:42

        Тем, что в один прекрасный, светлый момент можно будет убрать babel. С coffee такого сделать никогда не получится.
        Ну и естественно новые фишки, yield только-только поддержали в coffee, async-await судя по всему будет только в форке. Модули не понятно, будут или нет.


        1. benedikt
          03.04.2015 12:04
          -1

          Babel уже работает с возможностями ES7, предполагается, что проект будет поддерживать все будущие версии языка. И я вот сильно сомневаюсь, что в один прекрасный, светлый момент можно будет убрать babel, и не придется ли мне пользоваться им вечно! Если это так, то какая разница какой препроцессор мне использовать? CoffeeScript или Babel? Делают одно и тоже по сути.


          1. hell0w0rd
            03.04.2015 12:15

            Я бы еще поспорил с тем как делают, на coffee почти забили, посмотрите на то, с какой скоростью развивается babel.
            В babel можно отключать некоторые преобразования, таким образом не обязательно использовать все его возможности и например для iojs можно вообще половину отключить (let, const, arrow-function и еще пачку)


            1. benedikt
              03.04.2015 12:45
              -1

              на coffee почти забили

              Откуда у вас такая информация? Доказать можете?

              CoffeeScript занял свою нишу и используют его в основном программисты Ruby, Python, Haskell и Erlang.
              Если рост количества звёздочек на github на данный момент сейчас у babel выше, чем у кофе, это совсем не означает что CoffeeScript не развивается. Кофе как пользовался популярностью у Ruby, Python, Haskell и Erlang программистов, так и будет дальше пользоваться, не смотря на выходы новых стандартов. За это можете не переживать!


              1. Fesor
                03.04.2015 13:14

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


              1. hell0w0rd
                03.04.2015 13:24

                Помимо pulse просто посмотрите на issues. github.com/jashkenas/coffeescript/issues?page=10&q=is%3Aissue+is%3Aopen — есть баги, которые с 2011 года не пофиксили.
                Кстати судя по беглому просмотру issues с генераторами куча проблем не решенных.


                1. benedikt
                  03.04.2015 13:54
                  -1

                  Сами разработчики Кофескрипта писали когда-нибудь, что они прекращают развитие проекта?


            1. lolmaus
              06.04.2015 08:35
              +2

              Как человек, который без CoffeeScript жить не может, говорю: его развитие почти прекратилось. :(


              1. Serabas Автор
                06.04.2015 08:52

                Очень жаль. Однако, как человек, недавно начавший его использовать, спрошу — достаточно ли он развился на сегодняшний день, чтобы использовать в чем-то большом?
                Пробовал собирать сервера на coffee+express (без компиляции, через комманду coffee вместо node), пока не представляет особых неудобств на стадии «мало кода».
                Удобно ли мне будет ориентироваться в коде из, допустим, 400+ строк? Я конечно, понимаю, что лучше всё разбивать на модули и всё такое. Но… вдруг?)


                1. lolmaus
                  06.04.2015 19:04

                  Везде, где есть возможнотсь, я пишу на CoffeeScript. Никаких проблем с масштабированием он не создает, скорее, наоборот.

                  А модули нужны обязательно. Советую использовать модули ES6 через транспайлер в AMD.


              1. benedikt
                06.04.2015 18:55

                Может быть вы и правы. Но у меня возник такой вопрос.
                Куда развиваться? В какую сторону? Что вам сейчас не хватает в CoffeeScript?
                Просто ради интереса =)):


                1. lolmaus
                  06.04.2015 19:01
                  +2

                  Лично мне в CoffeeScript всего хватает. Есть ряд мелких пожеланий, но это несущественно.

                  В плане CoffeeScript не устраивает то, что и без того маргинальный язык с приходом ES6+ становится еще более маргинальным.

                  Я мечтаю о CoffeeScript 2, который генерировал бы ES6+ код. Он был бы избавлен от 90% фич CoffeeScript 1 (они были бы переложены на интерпретатор или транспайлер вроде Babel). Мы тут даже начали фантазировать на эту тему: github.com/babelscript/rfcs/pull/1 Пока никакой конкретики.

                  Отказаться от CoffeeScript в пользу ES6+ я не могу. Синтаксис JS контрпродуктивен. Если вы разделяете мою точку зрения, освойте CoffeeScript. На это у вас уйдет не больше недели. Если синтаксис JS не вызывает у вас отващения, учите ES6+. Хороший обзор фич можно найти на сайте Babel. Подключайте Babel к своему проекту и пишите на современном JS.


                  1. benedikt
                    06.04.2015 20:04

                    Я вот тоже не могу отказаться от CoffeeScript в пользу ES6+
                    Со многим где-то согласен, но опять есть вопросы =)):
                    Почему так важно писать на современном JS? Если транслируемый код из CoffeeScript в JavaScript корректно и быстро работает во всех броузерах и в Node.JS разве этого не достаточно?


                    1. lolmaus
                      06.04.2015 22:11
                      +2

                      На данный момент достаточно, но мир движется вперед, и вы не хотите однажды обнаружить, что остались на перроне.


                      1. benedikt
                        07.04.2015 10:38

                        Абсолютно с вами согласен. Мир движется вперед и думать о будущем нужно, чтобы потом не остаться на перроне. И вы как человек, который без CoffeeScript жить не может, как думаете, какое будущее ждет CoffeeScript?


                        1. lolmaus
                          07.04.2015 11:08
                          +1

                          Дальнейшая маргинализация. Он никуда не исчезнет, но будет терять популярность.

                          Я надеюсь, что наша задумка BabelScript когда-нибудь выстрелит, но движения в этом направлении пока нет.


                          1. benedikt
                            07.04.2015 13:37

                            Слава богу, хоть успокоили меня тем, что написали — «что он никуда не исчезнет».

                            Я полагаю сейчас не в пользу CoffeeScript играет тот факт, что он почти не развивается и в нем нет поддержки ES6. И поэтому, он по вашему мнению, будет терять популярность. Поправьте, если я не правильно вас понял. Я раньше полностью разделял это мнение. Но в последней версии CoffeeScript-а появилась поддержка генераторов ES6. И у меня появилась надежда. Сейчас идет обсуждение добавление фичи async / await (github.com/jashkenas/coffeescript/pull/3813), как вы думаете, стоит ли ждать в будущем в CoffeeScript поддержки каких-то хотя бы основных фич из ES6?


                            1. lolmaus
                              07.04.2015 15:25

                              Async/Await есть в IcedCoffeeScript. Я не особо вникал в этот синтаксис, потому что если он блокирующий, то это тупо, а если неблокирующий, то уже есть промисы.

                              > стоит ли ждать в будущем в CoffeeScript поддержки каких-то хотя бы основных фич из ES6?

                              На уровне функционала CoffeeScript сейчас поддерживает почти всё. Не хватает нескольких мелочей, с которыми вы вообще можете в жизни не столкнуться.

                              Вообще, такое ощущение, что ES6 тупо списали все фичи с CoffeeScript. А чтобы учитель не спалил, они внесли несущественные изменения: ...foo вместо foo... или, скажем, => вместо -> и т. п.

                              Вопрос развития CoffeeScript стоит в том, что он генерирует ES3 код, и этот факт никогда не изменится. Интерпретаторы развиваются, так что ES3 код скоро станет морально устаревшим. Будущее CoffeeScript я вижу в создании принципиально новой версии компилятора, синтаксис которого полностью подобен ES6+ и который генерирует современный ES6+ код.

                              Такой компилятор был бы намного легковеснее, чем нынешний CoffeeScript, поскольку он занимался только бы фичами, принципиально отсутствующими в ES6+, а всё остальное легло бы на плечи Babel или даже напрямую на интерпретатор, поддерживающий ES6+. И выучить такой язык было бы намного легче, чем CoffeeScript, так как он почти не отличался бы от ES6+.


                              1. benedikt
                                07.04.2015 16:34

                                Спасибо за исчерпывающий ответ.

                                > Интерпретаторы развиваются, так что ES3 код скоро станет морально устаревшим.

                                Вы имеете ввиду, что код который будет транслировать CoffeeScript в JavaScript в будущем перестанет работать в браузерах и в Node.JS?

                                > Вопрос развития CoffeeScript стоит в том, что он генерирует ES3 код

                                Я так понимаю единственный код, который сейчас CoffeeScript транслирует в ES6 — это генераторы, а все остальное это — ES3?


                                1. lolmaus
                                  07.04.2015 17:40

                                  > Вы имеете ввиду, что код который будет транслировать CoffeeScript в JavaScript в будущем перестанет работать в браузерах и в Node.JS?

                                  Это крайне маловероятно. Но он будет работать неоптимально. Вы просто посмотрите на ту кашу, которая получается у CoffeeScript на выходе, и представьте, что она может быть переписана на чистом ES.

                                  > Я так понимаю единственный код, который сейчас CoffeeScript транслирует в ES6 — это генераторы, а все остальное это — ES3?

                                  Именно.

                                  А поддержку модулей они хотят запилить как-то криво. Вместо того, чтобы сделать трансляцию в ES-модули, они собираются сделать какой-то ацкий комбайн, который в зависимости от конфигурации проекта может компилировать в ES, AMD или RequireJS. Над реализацией никто не работает, просто мэйнтейнер заявил, что он отказывается делать прозрачную трансляцию в ES-модули.


                                  1. benedikt
                                    08.04.2015 08:19

                                    > Но он будет работать неоптимально.

                                    Не оптимально в плане производительности?

                                    И ище один вопрос:
                                    Например, сейчас стандарт ES5, а у CoffeeScript на выходе ES3, но ведь никто не жалуется на то, что CoffeeScript транслировал их код в ES3, а не в ES5 сегодня.


                                    1. lolmaus
                                      08.04.2015 11:49
                                      +1

                                      > Например, сейчас стандарт ES5, а у CoffeeScript на выходе ES3, но ведь никто не жалуется на то, что CoffeeScript транслировал их код в ES3, а не в ES5 сегодня.

                                      Это потому что ES5 не отличается от ES3 по синтаксису. А ES6+ — отличается. Когда интерпретаторы будут нативно исполнять ES6+ код, то компактные конструкции ES6+ будут выполняться быстрее, чем их громоздкие ES3 аналоги.


                                      1. benedikt
                                        08.04.2015 14:47

                                        А если например громоздкая конструкция ES3 будет работать быстрее или также, чем компактный аналог ES6+ (такое ведь нельзя исключать?), вы бы тогда, что предпочли, чтобы разработчики CoffeeScript сделали:
                                        оставили на ES3 или переписали эту конструкцию на ES6?


                                        1. lolmaus
                                          08.04.2015 15:20
                                          +2

                                          .forEach() работает на 1500% медленнее, чем for (var i, i >= foo.length, i++). Но я не робот, чтобы писать эти for loops и каждый день спотыкаться об ошибку на единицу.


                                          1. benedikt
                                            08.04.2015 20:38

                                            Я хотел тут заметить, что ES6 — это да стандарт (факт неоспоримый), но важно не увлекаться и помнить об основной цели — писать «высокопроизводительный» код, который легко читать и сопровождать, вы согласны? По сути так ли важно, какой JavaScript на выходе ES3, ES5 или ES6? (я ведь все равно пишу на CoffeeScript!) — главное конечный код работает везде и работает быстро, вы согласны?

                                            Как мы видим генераторы ES6 уже добавлены в CoffeeScript и возможно что-то еще добавят из ES6. Если например в будущем 95% своего кода CoffeeScript будет транслировать в ES3, а 5% в ES6. Как думаете такой вариант многих устроит?


                                            1. Fesor
                                              08.04.2015 20:54

                                              Да госпади, пишите вы на своем CoffeScript сколько хотите. Вы знаете что происходит при трансляции? Как транслируется каждая конструкция? Тогда у вас нет проблем и вы можете жить счастливо.

                                              Если же касаться идеи транслируемых языков и совместить их с вопросом производительности, то тут выигрывают TypeScript и Dart (если учитывать проект SoundScript)


                                              1. benedikt
                                                10.04.2015 10:17
                                                -3

                                                Да щерт побери, пишите вы по своим стандартам сколько хотите. Вы знаете какая конструкция из нескольких вариантов работает быстрее? Тогда у вас нет проблем и вы можете жить счастливо.

                                                Ну вот вы пишите, что «кофе это кофе а ES2015 это стандарт»
                                                Я вроде бы согласен, что стандарты это хорошо, надо их знать, и все такое, но вот полностью соблюдать их — вопрос спорный.
                                                Например,
                                                есть стандарт CSS3 — но сейчас мало, кто пишет на чистом CSS3, многие используют препроцессоры Sass/LESS/Stylus.
                                                есть стандарт HTML5 — но многие предпочитают использовать различные шаблонизаторы.
                                                вместо JavaScript, предпочитают CoffeeScript/TypeScript/Dart.

                                                И все эти препроцессоры, шаблонизаторы используют, потому что удобно.
                                                Все пишут поверх стандартов. Сами стандарты не поспевают за нуждами разработчиков. Они вообще выходят исходя из потребностей разработчиков. Многие готовы даже игнорировать стандарты ради удобства. Удобство еще никто не отменял. Сейчас вообще стандарт — это то, что удобно, быстро, продуктивно и результативно. И почему тот факт, что ES6 это стандарт должен повлиять на чье-то решение использовать или не использовать CoffeeScript/TypeScript/Dart, если им удобно их использовать?


                                        1. Fesor
                                          08.04.2015 15:33

                                          На ES3 в в принципе не сможете часть функционала ES6 реализовать. На ES5 — да. А трансляция в ES5 всеравно будет еще нужна какое-то время. Что до «работать быстрее/медленнее» — крайне маловероятно. все это только синтаксис, ничего более. Внутри, на уровне байт кода, все примерно так же как было и в ES5.


  1. lolmaus
    06.04.2015 08:20

    Вы интуитивно пришли к функциональному программированию, но, право, jQuery — не самый подходящий пример для решения задачи.

    Я сам с функциональным программированием знаком поверхностно, но полагаю, что ваша задача решалась бы там с помощью функций filter и map, а чтобы не развертывать алгоритмы выборки и обхода каждый раз, используется каррирование.

    Попробуйте ramdajs.com/.


    1. Serabas Автор
      06.04.2015 08:30

      Возьмём, к примеру, тот же After Effects (о котором я скоро напишу).

      Что лучше (проще, ламповее, круче, называйте, как хотите =)):

      	var composition = app.project.activeItem;
      	
      	var filtered = composition.layers.filter(function (layer) {
      		return layer.active;
      	});
      


      или:

      	var filtered = $(':active');
      


      1. lolmaus
        06.04.2015 08:34

        Да ради бога.

        Я просто хочу сказать, что есть более простые и экспрессивные способы написать тот же самый функционал без мимикрии под jQuery.


        1. Serabas Автор
          06.04.2015 08:49

          Тут согласен. Просто я был вдохновлён самим jQuery и вынес свои мысли по этому поводу на всеобщее обозрение.
          Однако реакция хабражителей оказалась не соответствующей ожиданиям. Постараюсь в следующей статье вынести как можно больше фактов и полезностей. Лично мне это сильно развязало руки при работе с большими данными. ИМХО, уж простите.


    1. lolmaus
      06.04.2015 08:31

      Впрочем, можно и безо всяких библиотек и каррирования обойтись при желании:

      var isEven  = function(item) { return item % 2 === 0; };
      var getEven = function(item) { if (isEven(item)) return item; };
      var getOdd  = function(item) { if (!isEven(item)) return item; };
      var addNumber = function(number) {
        return function (item) { return item + number; };
      };
      
      console.log(
        [2, 3, 4, 5, 6, 7]
          .filter ( getOdd       )
          .map    ( addNumber(2) )
      ); // => [5, 7, 9]
      


      Демо: jsbin.com/ripojo/1/edit?js,output


      1. Serabas Автор
        06.04.2015 08:54

        При желании можно обойтись и ассемблером )
        Моя задача — разработать такую штуку, которую можно будет встраивать везде, где есть Javascript и которая будет развязывать руки программистам.
        Кстати очень удобно с ней работать из всякий консолей. В следующей статье я об этом обязательно расскажу.