Это перевод статейки о некоторых не совсем очевидных прикольных возможностях, которые предоставляет ES6 стандарт JavaScript'а. В статье время от времени проходит нечто наркоманское, так что вполне возможно я не смог перевести всё достаточно качественно. Если нашли косяки, напишите мне об этом — поправлю.


{в оригинале здесь была какая-то непонятная гифка с обезьяной, которую я как-то не очень понял, оттого и не буду её здесь ставить}


Вот вам несколько методов на основе ES6, которые на самом деле не совсем трюки — просто, используя некоторые вещи из нового синтаксиса, мы можем неплохо сократить код, улучшить его читаемость, или, возможно, просто весело провести время. Я (автор оригинала, не автор этой статьи на хабре — прим. пер.) планирую собирать больше в этой статье, поэтому, пожалуйста, не стесняйтесь добавлять её в закладки и проверять время от времени. Ну и если у вас тоже есть какие-то забавные трюки, которые я не упоминаю здесь, пожалуйста, напишите об этом!


Деструктуризация


Деструктуризация — моя самая любимая часть синтаксиса ES6. Теперь она есть и в Node 6, так что это дело можно использовать и на фронтенде, и на серверной стороне. Для больших подробностей можно почитать разъяснение этого дела на сайте Mozilla (там тоже на русском, кстати), если вы не знаете основу, а для тех, кто МБ/НЧ — это возможность легко назначать определённым переменным какие-то значения во вложенных объектах.


Парочка простых примеров:


// можно деструктурировать массивы
const [a, b] = [1,2]; // a = 1, b = 2

// можно деструктурировать ключи в объектах
const { a } = { a: 3 }; // a = 3

// даже параметры функций
function foo({ a }) {
  console.log(a);
}

foo({ a: 4 }); // выведет 4

Переименование


Одна из фишек деструктуризации, о которой вы, возможно, не знаете — это возможность переименования по ходу дела. Если вы использовали ES6 модули, вы можете знать, как работает оператор импорта при переименовании импортированных объектов и, возможно, задавались вопросом, почему так не получается делать при деструктуризации. Ну, там на самом деле просто чуток другой синтаксис:


// простое переименование для избежания коллизий или просто для красоты.
const first = 5;
const { first: second } = { first: 3 };

console.log(second); // выведет 3

// переименовать для другого API с использованием расширенного использования присваивания
function verifyUser({ userId: id }) {
  return User.update({ id, verified: true });
}

В сочетании с параметрами по умолчанию


Параметры по умолчанию позволяют вам указывать значения параметрам, которые не были переданы пользователем, но что если вы собирались деструктуризовать их, когда они приходят? Не проблема… У нас есть левая сторона присваивания (a.k.a. lvalue) с параметрами по умолчанию, так что вы можете использовать деструктуризацию и здесь!


function defaults({ a, b } = { a: 1, b: 2 }) {
  console.log('a', a); 
  console.log('b', b);
}

defaults();
// a 1
// b 2

defaults({ a: 42, b: 32 });
// a 42
// b 32

// Будьте осторожны с множественными параметрами!
// Вся правая сторона будет заменена вашими аргументами.
defaults({ a: 87 });
// a 87
// b undefined

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


function defaults({ a = 1, b = 2 } = {}) {
  console.log('a', a); 
  console.log('b', b);
}

defaults();
// a 1
// b 2

defaults({ a: 42, b: 32 });
// a 42
// b 32

// множественные параметры? Нет проблем, просто укажите то, что вы хотите изменить
defaults({ a: 87 });
// a 87
// b 2

Присваивания, ветвления и листья


Вы даже можете деструктурировать глубокий объект или массив! Но промежуточные ключи объектов не будут присвоены в это время. Что делать, если вы хотите присвоить какие-то промежуточные ключи и какой-то глубокий узел? Просто спросите о нём! Другими словами, как мы покажем в нижеидущем примере, вы можете просто объявить любую переменную, которую хотите (промежуточное соединение в данном случае) и использовать её снова как спецификацию для перехода на другой уровень (промежуточный -> вложенный) (вот же-ж наркомания… — прим. пер.).


const {
  topLevel: {
    intermediate,    // объявление промежуточной
    intermediate: {
      nested         // объявление вложенной
    }
  }
} = {
  topLevel: {
    intermediate: {
      nested: 56
    }
  }
};

// intermediate is { nested: 56 }
// nested is 56

Идиоматические аргументы командной строки для Node


Node.js прекрасная вещь для написания скриптов. Для аргументов командной строки вы можете извлечь их из process.argv. Если вы делаете что-то сложное, или действительно нечто предназначение для использования людьми, лучше будет заюзать что-нибудь вроде yargs для их парсинга. Но… если у вас есть скрипт, который просто берёт небольшое количество аргументов, вы можете использовать деструктуризацию массива для того чтобы пропустить первые два аргумента (обычно путь к Node.js и путь к скрипту) и присвоить остальные переменным.


#!/usr/bin/env node

// пропустить первые два аргумента, которые являются node.js и этим скриптом
const [,,filepath] = process.argv;

doSomethingFSLike(filepath);

Расширенные литералы объектов


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


const moment = require('moment');
const PERIOD = moment.duration(3, 'days');

module.exports = {
  PERIOD,

  isWithinPeriod(test) {
    return moment().add(PERIOD).isAfter(test);
  },
};

/// В то же время, в нашем файле теста...

const timeUtils = require('./time-utils');

describe('timeUtils.isWithinPeriod', () => {
  it('ложно за пределами его собственного временного периода', () => {
    const beyondPeriod = moment().add(timeUtils.PERIOD).add(timeUtils.PERIOD);
    assert(timeUtils.isWithinPeriod(beyondPeriod) === false);
  });
});

Вместе с JSX


Окей, это не ES6 конечно, но вы можете использовать некоторые фичи ES6 вроде короткого значения свойства очень удобным образом вместе с JSX.


function WhySoManyProps(props) {
  const user = extractUser(props);
  const fudge = calculateFudge();
  const bits = computeBits();

  // Это тааак избыточно.
  return <SomeComponent user={user} fudge={fudge} bits={bits} />;
}

function Shorthand(props) {
  const user = extractUser(props);
  const fudge = calculateFudge();
  const bits = computeBits();

  // отправим все новые переменные, которые имеют такое же имя, как и свойства
  return <SomeComponent {...{ user, fudge, bits }} />;
}

Правда, такой подход не очень рекомендуют использовать в официальной документации к React.js — прим. переводчика.


Object.assign


Object.assign — это фантастическое новое дополнение, которое очень помогает сохранять вещи иммутабельными (или, по крайней мере, делать только эфемерные мутации к промежуточным объектам). Но знаете ли вы, что их можно устанавливать и для значений массивов в том числе?


const original = [0,1,2,3];
const copy = Object.assign([], original, { 2: 42 }); // [0,1,42,3]

console.log(original);
// [ 0, 1, 2, 3 ]

console.log(copy);
// [ 0, 1, 42, 3 ]

Ваши предложения?


Есть какие-то другие трюки, которые вам нравятся, и которые отсутствуют в данной статье? Поделитесь ими в комментариях!

Поделиться с друзьями
-->

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


  1. jaybekster
    28.10.2016 15:03

    Да, можно делать так:

    const {a: {b: {c: {length}}}} = {a: {b: {c: []}}};
    


  1. a-motion
    28.10.2016 15:07
    -1

    Самая наркоманская строка там «Node.js прекрасная вещь для написания скриптов».


    1. saggid
      28.10.2016 18:16
      +4

      Я не знаю, но по-моему, всё-таки, пилить скрипты на баше — вот это реально по-наркомански. Особенно после той статьи о подводных камнях Bash, которая недавно вышла на хабре. Почти 50 пунктов, на каждом из которых у меня мозг чуть ли не разрывает.


      Может лучше всё-таки на Node.js/PHP/чём-то ещё их писать в перемешку с вызовом простых bash-команд? Bash — полезная штука, но только когда его немножко) Дальше реально начинается какое-то наркоманство.


      1. a-motion
        28.10.2016 18:34
        -7

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


        1. TyVik
          28.10.2016 18:37
          +1

          А про питон все забыли :(


          1. a-motion
            28.10.2016 19:39

            Питон слишком многословен, а руби не всегда есть из коробки.


            1. Igelko
              29.10.2016 09:40

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


        1. raveclassic
          29.10.2016 13:20
          +1

          В-пятых, JS как язык не имеет ни одного преимущества перед даже PHP, так что вкупе с перечисленным нет ни единого аргумента в пользу написания на нем скриптов, кроме «я увечный, и больше ничего не осилил».
          Мне кажется, у Вас наболело.


          1. a-motion
            29.10.2016 16:51
            -4

            Есть несколько языков, в основе которых лежит один сплошной невероятный design flow. Они неконсистентны, ввиду чего грабли разложены повсюду, заботливо прикрытые костылями. И bash script никак не в этом ряду. А js там на первом месте.

            Все нарекания в адрес баша сводятся к: «я бац-бац-и-запустил, а оно мне попереименовывало файлы», а все ответы — к «сходи почитай документацию сначала». Баш может выглядеть гораздо менее дружелюбным, но он прост и — главное — предсказуем.

            С js все не так. И, самое главное, мне придется полчаса накатывать обновления инфраструктуры прежде чем я смогу обработать список всех файлов в папке. А чтобы поделиться этим скриптом с женой (в соседнем аккаунте), мне придется объяснять ей, как накатывать ноду. Это не нормально.

            Питонисты воюют с рубистами на тему «у кого язык круче». У джсистов война идет про библиотеки. Что, как бы, многое говорит про сам язык. Я не встречал такого количества транспайлеров ни в один другой язык. Даже на COBOL’е до сих пишут его родным синтаксисом. А транспайлер в JS не написал только самый ленивый.

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


            1. saggid
              30.10.2016 02:55
              +1

              Я отказываюсь верить в вашу bash-религию.


              1. a-motion
                30.10.2016 08:26
                -4

                Класическая фраза всех людей, у которых нет аргументов.

                Нет никакой религии и я никогда не пишу ничего сложнее hello-world на баше. Из этого никак не следует, что js пригоден для написания шелл-скриптов.

                Пока вы себе на коленке пишете что-то — пишите хоть в машинных кодах. Но объективная реальность такова, что как только вам захочется написать что-то, чем будут пользоваться люди, вам придется написать это на баше, перле, или, в худшем случае — питоне, потому что 99% людей увидев, например, инсталлятор на js, уйдут навсегда.

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


                1. saggid
                  30.10.2016 10:10
                  +2

                  Да это просто шутка была. У меня полно аргументов против того что вы пишете, я даже написал ранее некоторые, но вы даже их не заметили и продолжили нести в массы свои «единственно истинные» убеждения.


                  Писал я на баше всякие вещи. Больше не желаю: на пхп в данный момент лично мне намного удобнее. Node.js также будет более удобен для лично меня, чем пресловутый баш с тонной своих магических приколов.


                  Ну и что, что установить их надо на сервер? Это так сложно, серьёзно? Мне еще обсуждать это с вами?


                  1. a-motion
                    30.10.2016 10:59
                    -6

                    > Ну и что, что установить их надо на сервер?
                    > Это так сложно, серьёзно? Мне еще обсуждать это с вами?

                    Не-не, со мной это обсуждать бессмысленно.

                    Это не сложно, это вредно. Я не могу себе позволить в продакшн тащить какое-то говно только потому, что программисты настолько криворуки, что пишут скрипты на JS. Вот и все. И PHP там, очевидно, тоже нет.

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


                    1. saggid
                      30.10.2016 11:38
                      +3

                      Очевидно, что мне за это даже платят деньги. Мне важнее, чтобы код, на основе которого работает система, был как можно более понятен и удобен для дальнейшего развития, и не важно, что это: скрипт для бекапа или обработчик данных, или вебсайт. Если для этого надо будет установить на сервер что-то кроме стандартного баша — мы обязательно сделаем это.


                      1. a-motion
                        30.10.2016 12:02
                        -7

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

                        Тогда что там делают JS и PHP?

                        Кроме того, зоопарк всяких не имеющих к делу приблуд на сервере — всегда признак безграмотности архитекторов (и ведет к взрывообразному увеличению количества потенциальных уязвимостей.)


                        1. TheShock
                          30.10.2016 12:13
                          +5

                          Глупости вы говорите, если у вас есть штат JS-ников, которые занимаються своей работой, то пусть они лучше пишут скрипты на node.js, качественнее будет. Аналогично, если идет разработка на каком-нибудь Symfony, то скрипты отлично пишутся на php. И зачем первым и вторым писать что-нибудь на перле? Чтобы потом не было кому поддерживать? Или чтобы допускать детские ошибки?


                          1. a-motion
                            30.10.2016 13:37
                            -7

                            Давайте вы за себя говорить станете, а советы, что и как делать мне — давать перестанете?

                            Потому что в моем мире «JS-ник, который занимается своей работой» — в штате не появится никогда. Он на аутсорсе, за три копейки, и к продакшену я его близко не подпущу.

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


                            1. TheShock
                              30.10.2016 14:35
                              +6

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


                              1. a-motion
                                30.10.2016 16:46
                                -4

                                > Глупости вы говорите
                                > давайте вы перестанете хамить окружающим из-за своего узкого видения

                                Вы, стало быть, в ветке появились, от входа приплели два аргумента ad hominem, а хамлю — я?

                                Изящно.

                                Если я кого и обижал — так это Javascript, но тут мне особо стараться не пришлось, за меня это прекрасно сделали его создатели и матушка-природа.


                                1. TheShock
                                  30.10.2016 17:08
                                  +2

                                  программисты настолько криворуки, что пишут скрипты на JS.


                                  безграмотности архитекторов


                                  Да, хамите вы. и оскорбляете не язык, а программистов, которые на нем пишут. И, как я уже сказал, на JS пишут не от безграмотности и криворукости, а потому что иногда это удобней. И уж явно большинству команд писать скрипты на Python, JS, PHP, Ruby, удобнее, чем на Перле, ибо тех, кто знает Перл меньше, чем тех, кто не знает.


        1. alek0585
          29.10.2016 21:26

          А похапе есть фактически везде из коробки?


          1. a-motion
            30.10.2016 09:50
            -1

            Если вы не в состоянии прочесть и понять комментарий, на который собираетесь ответить, лучше промолчать.

            Но мне не сложно: я для не очень внимательных повторю основную мысль. Bash есть из коробки. PHP там фигурировал в совершенно ином контексте: JS — единственный из тех примерно двадцати языков, которыми я владею, который ужаснее PHP по продуманности парадигмы и, как следствие, количеству разложенных граблей, неконсистентности и удобству применимости в серьезном проекте.

            А так–то можно на чем угодно Тьюринг–полном написать что угодно работающее. Но зачем?


            1. izzholtik
              31.10.2016 10:55

              Ещё перл часто из коробки есть. С питоном сложнее.


              1. a-motion
                31.10.2016 11:07
                -2

                Я это написал в первом же комментарии в этой ветке.

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

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

                Так что вы тут поаккуратнее с перлом :)


                1. saggid
                  31.10.2016 11:24
                  +3

                  Извините, это вы-то у нас — профессионал, серьёзно?)


                  Человек, доводы которого — "этого нет из коробки в моей ОС", или "моей жене придётся объяснять как работает пакетный менеджер node.js".


                  Причём здесь вообще ваша жена, скажите мне пожалуйста, мой друг-профессионал?) Какое мне дело до того, придётся мне ей что-то объяснять, или не придётся? Вы серьёзно на этом основании отбираете себе сотрудников в организацию?) Придётся ли вашей жене объяснять, чтобы запустить то, что написал ваш сотрудник?


                  Ну откуда вы такой вылезли, скажите мне пожалуйста?)


                1. saggid
                  31.10.2016 11:45
                  +2

                  Большинство ваших доводов либо устарели, либо просто некорректны. У вас какая-то ненависть к современным языкам разработки, вроде Node.js/PHP/Ruby/Python, хотя их успешно используют сотни тысяч людей по всему миру.


                  Неужели весь смысл подобных бесед на различных айтишных форумах — это завалить друг друга оскорблениями, утонуть в нерациональных доводах и попытаться самоутвердиться на этой низменной основе? Есть ли хоть что-то иное в ваших намерениях помимо этого, мой друг? Не пришло ли время отбросить эти глупые дела и заняться чем-то более благим?


                  1. a-motion
                    31.10.2016 12:13
                    -1

                    > У вас какая-то ненависть

                    Вы диагнозы-то по юзерпику завязывайте ставить.

                    > современным языкам разработки, вроде Node.js/PHP/Ruby/Python

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


                    1. justboris
                      31.10.2016 12:36
                      +1

                      напомню, что изначально в этом треде обсуждалось, пригоден ли JavaScript/Node.js для написания скриптов.


                      И как следует из самого названия JavaScript — это скриптовый язык. В стандартой поставке Node есть модули работы с файлами и сетью, поэтому если команда не против, то можно использовать и Node, особенно если она уже для чего-нибудь еще используется


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


                    1. saggid
                      31.10.2016 12:51
                      +3

                      Честно, баш меня пугает намного больше, чем Node.js. В этом вся суть. Яваскрипт изучить, по-моему, всё-таки проще. По крайней мере, я его успешно изучил и использую. Хвала Всевышнему, очень хороший инструмент для работы, как в браузере, так и на сервере.


                      Что касается bash'а — то вы мне объясните, как так может быть, чтобы мы использовали в своём арсенале то, в чём бывает подобное:


                      for i in $(ls *.mp3); do    # Неправильно!
                          some command $i         # Неправильно!
                      done
                      
                      for i in $(ls)              # Неправильно!
                      for i in `ls`               # Неправильно!
                      
                      for i in $(find . -type f)  # Неправильно!
                      for i in `find . -type f`   # Неправильно!
                      
                      files=($(find . -type f))   # Неправильно!
                      for i in ${files[@]}        # Неправильно!

                      Ну вот как это назвать? Это не просто "сходи почитай документацию". Это называется "иди и перечитай сотни мегабайт текста, чтобы достичь истинного просветления". Да нет у меня времени, чтобы столько заниматься изучением баша. Мне проще яваскрипт изучить, честно. На это времени уйдёт меньше.


                      Я использую баш уже лет 7-8. Я начинал ещё с шестой убунты. Я постоянно работаю в линуксе уже многие годы. Я почти каждые пять минут обращаюсь к командной строке в своём YaKuake. Но писать на баше большие скрипты я больше не собираюсь. Спасибо, не надо. В для этого достаточно других инструментов, которые делают это дело лучше, чем баш. А башу пусть остаётся удел набивания одиночных команд. Там он прекрасно справляется.


                1. Igelko
                  31.10.2016 13:09
                  +3

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


                  1. Нужен ручной/по расписанию перенос пользователя из одного инстанса БД в другую.
                  2. Нужен тяжёлый фоновый расчёт, выполняемый по расписанию.
                  3. Нужны какие-то разовые наколеночные отчёты по данным БД.

                  И то и другое — самые настоящие скрипты. И в гробу я, и как разработчик, и как админ, видел поддерживать две имплементации моделей с валидацией на двух разных языках, просто потому что "не хочется тащить всякое говно на сервер".


                  Да, я в целом согласен, что использовать js для написания консольных инструментов не очень удобно, потому что стандартная библиотека откровенно бедная => требуется тащить много стороннего кода, есть проблемы в языке => добавляются классы возможных ошибок (без тестов на js писать невозможно совсем).


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


                  1. a-motion
                    31.10.2016 14:21
                    -2

                    > логично использовать тот же язык программирования,
                    > на котором реализовано основное приложение

                    Разумеется, с этим никто и не спорит.

                    > Нужен ручной/по расписанию перенос пользователя из одного инстанса БД в другую.

                    У вас что-то не так с архитектурой. Это задача для самой базы, а не для стороннего скрипта.

                    > Нужен тяжёлый фоновый расчёт, выполняемый по расписанию.

                    Менеджеры задач придуманы как раз для этого: https://www.npmjs.com/package/sidekiq

                    > Нужны какие-то разовые наколеночные отчёты по данным БД.

                    Я в таком случае вкручиваю ручки под суперадмином во фронтенд и дергаю их хоть с Багам через веб-интерфейс. Не могу себе представить ситуацию, когда скрипт командной строки тут уместен.

                    Я никогда не предлагал сделать еще одну имплементацию бизнес-логики на баше (или вообще на чем-то другом). Просто если сначала думать, а потом делать — скрипты на js (а еще фронтенды на шелле, базы данных на хаскеле и бекэнды на си) писать не придется. Вот и все.


                    1. Igelko
                      31.10.2016 16:07
                      +1

                      У вас что-то не так с архитектурой. Это задача для самой базы, а не для стороннего скрипта.

                      Может быть да, а может быть нет. Далеко не всё можно объяснить "кривой архитектурой". Допустим, вам надо перенести юзера/кусок данных на котором воспроизводится баг из основной БД в тестовую. Или например сериализовать маленький кусочек данных, чтоб потом подложить их в качестве фикстур юнит-тестам.
                      Это удобно. Также для уже живущих проектов нельзя просто так взять и выкинуть существующим mysql/postgresql etc, чтоб впилить туда базу с автоматическим шардингом — это может просто угробить проект.


                      Менеджеры задач придуманы как раз для этого: https://www.npmjs.com/package/sidekiq

                      Боже ты мой, тащить "кусок говна" на руби, когда у нас и так есть "кусок говна" на nodejs? Появляется ещё целых 2 лишних сущности (redis и сам менеджер задач). Не находите это перебором во многих случаях? Мне всего-то надо раз в час подсасывать csv-шку или выливать отчётец в шару. Тащить в проект ещё 2 сущности, которые надо мониторить для этого — нет, спасибо. А если этот проект ещё и тиражировать требуется? Затраты на администрирование растут ещё быстрее. Чем меньше разнородных частей в архитектуре, и чем проще каждая часть — тем лучше.


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

                      Это если вы заранее знаете, какой отчётец надо сделать. А если нет? И когда вы дёргаете построение отчёта через веб, вы надолго занимаете воркер, который нужен веб-части. Двухчасовой отчёт просто отвалится по таймауту. Админку на отдельных мощностях поднимать и держать?
                      Часто проще наговнокодить на коленке какой-то скрипт, потом согласовать 2-3 раза с заказчиком отчёта, и лишь потом закатать его в джоб, запускаемый по расписанию, да сдать админам.


                      Просто если сначала думать, а потом делать — скрипты на js писать не придется.

                      Тут есть проблема. Рынок разработчиков конечен. В небольших городах он ещё более конечен. Можно конечно набирать разработчиков, умеющих в много разных языков подряд, но тогда они будут дороже. За тотальный js говорило:


                      • V8 — это быстрый и довольно качественный рантайм, нетребовательный к ресурсам. (если сравнивать с python/ruby и подобными)
                      • быстрое прототипирование
                      • относительная немногословность
                      • достаточное количество библиотек.
                      • достаточное количество грабей в гугле, благодаря большому комьюнити.
                      • Можно валить на одного разработчика и фронтенд и бекенд части какой-то фичи. Тимлид потом побъёт палкой на код-ревью и в итоге получится более-менее рабочее. И можно будет катить фичи, даже если кто-то заболеет / уйдёт в отпуск.
                      • снижение требований к разработчику. Народ, когда читает вакансии меньше пугается и идёт собеседоваться.

                      Против:


                      • Язык так себе. Частично купируется ES6/Typescript, драконовски настроенным линтером, и тотальными юнит-тестами.
                      • Библиотек хоть и много, но много из них весьма посредственного качества. То и дело ломаются. Чинить через CI и битьём по рукам, чтоб не тащили всё подряд в проект.
                      • dependency hell.
                      • В советах в гугле МНОГО говнокода, всё равно требуется головой думать (3 раза ха).

                      Есть плюсы, есть минусы. Плюсы пока перевешивают.
                      // Правда какие-то инструменты мы всё равно пишем на питоне — если есть требование к минимизации зависимостей и нет завязки на модели БД.


                      1. a-motion
                        31.10.2016 16:49
                        -3

                        Ну вот, вы говорите разумные вещи, сразу интересно стало.

                        Я на sidekiq ссылку дал просто потому, что он первый подвернулся: это я несомненную глупость сморозил. Но я уверен, что кто-то что-то подобное на чистом js давно написал. Сам же «менеджер задач» лишней сущностью не бывает никогда, вы самому себе вчерашнему миллион раз спасибо скажете, когда можно просто будет в очередной раз просто выплюнуть куда-то в заоконный космос задачу, а оно все само по времени разрулит. Ручки из фронтенда — они ровно про это, я уже забыл, как это: жить без крона. Разумеется, я не имел в виду нагружать воркер.

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

                        Да, программистов проще найти на руби/питоне (на js не смотрел, уверен, что тоже), но зато эрланг позволяет сразу зачеркнуть такой широкий круг проблем, что о выборе не жалею ни разу. Да, фронтенд пришлось отделить в отдельную команду, зато у нас _совсем_ нет связности между ними и куски легко пробуются на Elm’e, например (пока ощущения позитивные).

                        Ну и самое главное: я понимаю, что выбор языка может быть определен перпендикулярными требованиями, но все задачи, описываемые вами, по уму решаются не скриптами, а на коленке — скриптами, запускаемыми из консоли ноды. Если у вас есть просто скрипт в вакууме, который загружает лишнюю ноду в продакшене — значит где-то что-то пошло не так. И да, все умеют и могут в таком случае вбить костыль, но по уму все-таки так делать не нужно.

                        Я же с этого начинал, причем довольно дружелюбно. У меня вот атом сегодня отказался из исходников собираться, я полез смотреть, что у меня не так с этим зоопарком, и мне чуть худо не стало. Даже go в свете написания скриптов выглядит изящней, он хотя бы не запутается в собственных зависимостях :)


                1. alek0585
                  04.11.2016 03:30

                  >коллеги хоть подохнут
                  Ваши коллеги тоже думают так?


                  1. a-motion
                    04.11.2016 22:02
                    -1

                    Думают как? Что задачи нужно решать при помощи предназначенных для этого инструментов? — надеюсь, что да.


    1. abyrkov
      29.10.2016 04:10

      Сам по себе — нет. Вкупе с npm — да.
      Например, нужно написать одну команду npm для установки Express + пара строк.
      Полнофункциональный сервак готов, чего никак не скажешь о PHP, Bash или Python.


      1. a-motion
        29.10.2016 09:18

        Я даже затрудняюсь как-то это прокомментировать. Тут бред все, от первого до самого последнего слова. Вы хоть понимаете, что такое «скрипт» в данном контексте?

        При чем тут вообще сервер? (Кстати, на питоне, например, вообще ничего устанавливать не нужно, чтобы запустить сервер — `python -m SimpleHTTPServer` и в путь).


        1. Igelko
          29.10.2016 09:47
          +1

          справедливости ради могу сказать, что производительность express значительно выше, чем у SimpleHTTPServer. Корректнее было бы сравнить его с tornado/TwistedWeb с прикрученным greenlet.


          1. a-motion
            29.10.2016 11:05

            Я единственный тут помню, что мы в топике про _шелл скрипт_? Откуда, ради всего святого, тут вообще взялась производительность веб-серверов?

            Я просто ответил на «чего никак не скажешь о PHP, Bash или Python» (чего, разумеется, делать не стоило, потому что «PHP, Bash или Python» через запятую как бы сразу закрывают тему).


            1. Igelko
              29.10.2016 11:41

              почему шелл-скрипт, а не CGI, скажем, которые, мог иметь ввиду автор жирного наброса комментария выше, и возможно даже автор поста?


              я просто прицепился ко второму вашему предложению и отметил, что сравнивать реализации express и SimpleHTTPServer некорректно.


              С тем, что на js ужасно неудобно писать консольные утилиты из-за ужасно бедной стандартной библиотеки и отсутствия в стандартной поставке дистрибутивов, я не спорю.


        1. surefire
          29.10.2016 11:06

          $ python -m SimpleHTTPServer
          /usr/bin/python: No module named SimpleHTTPServer


          1. xel
            29.10.2016 11:16
            +1

            Возможно у вас третья версия.

            python3 -m http.server
            


      1. Igelko
        29.10.2016 09:45
        -1

        никогда, прошу вас, никогда не деплойтесь через npm install на продакшне.
        Ворох зависимостей в 5+ уровней в глубину — это не то, что можно проконтролировать.
        Ну может вас ещё спасёт приколоченный гвоздями снапшот зеркала npm, с зафиксированными намертво версиями пакетов.


        1. saggid
          30.10.2016 03:01

          Есть ещё такая штука как yarn, если вам хочется больше скорости на деплое. Он правда со своими приколами некоторыми, из-за которых нам у себя на продакшене его заюзать, к сожалению, не удалось. Но у нас немного специфичная проблема была.


          1. Igelko
            30.10.2016 19:01

            yarn появился без году неделя, и я на него ещё не смотрел.
            И проблема не в скорости де.
            Проблемы установки npm install и подобными инструментами в следующем:


            • большинство транзитивных зависимостей нефиксированы. т.е. на прод внезапно может приехать новая версия пакета в транзитивных зависимостях, которая всё сломает.
            • часто требуется выполнить некоторый набор gulp/grunt-тасок для сборки (минификация итп задачи). Не хочется тащить devDependences на продакшн ради этого.
            • это не работает, если отсутствует интернет у килента.
            • это может не работать, если требуется собирать сишные биндинги. На продакшне требуется компилятор и заголовочные файлы.
            • среда на продакшене потенциально нестабильна — может приехать новый libc и всё сломать (но это уже очень маловероятно).
            • из прошлых пунктов следует невоспроизводимость билда — на проде может получиться другое сочетание, нежели в среде разработки и тестинге.

            Вышеприведённые пункты можно решать разными способами.
            Мы для наших проектов выбрали сборку докер-образа из которого потом выкидывается всё лишнее и делается его компактизация через docker export | docker import. Получается не зависящий ни от чего неизменяемый кусок файловой системы, на которой есть только то, что реально нужно для работы приложения.


            У меня к вам вопрос — yarn может решить какие-то проблемы из этих и как?


            1. saggid
              31.10.2016 07:11

              На их главной странице всё расписано)


              Yarn caches every package it downloads so it never needs to again. It also parallelizes operations to maximize resource utilization so install times are faster than ever.

              Yarn uses checksums to verify the integrity of every installed package before its code is executed.

              Using a detailed, but concise, lockfile format, and a deterministic algorithm for installs, Yarn is able to guarantee that an install that worked on one system will work exactly the same way on any other system.

              В общем, зависимости фиксируются, для них также создаётся кеш. Поэтому, определённый набор описанных вами проблем решается с помощью этого самого йарна. Ну и ещё, yarn написали в Фейсбуке, где его активно и используют. Думаю, это достаточно весомый повод в сторону того, что он действительно решает задачи деплоя Node.js приложений.


              Это то, что знаю я в данный момент. Но, как я сказал, мы у себя yarn не используем, на самом деле в силу простой банальности: он немного слишком умный :) Берёт и переносит зачем-то наши bower зависимости в папку модулей npm, когда нам вообще-то вовсе не нужно было этого делать. Разбираться было лень, и мы просто вернулись обратно на npm. В данный момент это не слишком сильно мешает, а описанные вами проблемы нас смущают не так сильно. Видимо, проекты наши отличаются своими задачами.


              1. murzilka
                31.10.2016 19:44

                > Думаю, это достаточно весомый повод в сторону того, что он действительно решает задачи деплоя Node.js приложений.

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


        1. lazypacman
          30.10.2016 03:22
          +1

          Ворох зависимостей в 5+ уровней в глубину — это не то, что можно проконтролировать.
          Неактуально начиная с npm третьей версии
          Ну может вас ещё спасёт приколоченный гвоздями снапшот зеркала npm, с зафиксированными намертво версиями пакетов.
          Чем не устраивает npm shrinkwrap?


          1. Igelko
            30.10.2016 18:46

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


            1. bromzh
              31.10.2016 07:34
              +1

              на продакшене неожиданно становятся нужны компилятор, заголовочные файлы итд.

              Может проблема в том, что вы собираете на продакшене (что обычно не стоит делать), а не на билд-сервере?


              1. Igelko
                31.10.2016 10:24

                Билд-окружение обязано иметь одну особенность — нужно, чтобы оно по версиям пакетов/abi совпадало с продакшеном. Это не всегда возможно (при тиражировании ПО, например) и несёт в себе некоторый риск.


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


                1. bromzh
                  31.10.2016 12:42

                  нужно, чтобы оно по версиям пакетов/abi совпадало с продакшеном

                  Если итоговое js-приложение должно работать в браузере, то никакие пакеты на проде не нужны, так как всё собирается на билде и заливается по ssh на прод.


                  Если итоговое js-приложение — это что-то server-side на ноде, то вероятно, билд сервер вообще не нужен. Можно собирать локально перед пушем, и в репозиторий включить node_modules. Для чистоты можно поднять vagrant с окружением идентичным проду, или намутить docker-контейнер.


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


                  1. Igelko
                    31.10.2016 13:20

                    Про фронтенд согласен, всё просто. Сделал gulp build и потом вывалил dist в каталог со статикой.


                    С полным приложением всё немного интереснее.
                    В итоге мы и собираем docker-контейнер, чтобы ни от чего не зависеть.


                    Если вам надо, например, поработать с oracle, то:
                    1) на сервере обязаны стоять клиентские библиотеки.
                    2) вы обязаны собрать биндинги ровно под эти версии библиотек и с бинарно совместимыми версиями других пакетов.


                    Это не вина npm и ноды. Это дополнительное требование, которое должно соблюдаться.
                    Решения:
                    1) тащим на продакшен компилятор и там собираем всё. У админа болит голова и плохо спится, потому что куча всякой дряни на сервере и что-то может не собраться в самый ответственный момент.
                    2) Собираем отдельно и копируем node_modules, то есть риск, что версии бинарей могут не сойтись и приложение на продакшен сломается (это почти ок)/ будет вести себя странно (а вот это плохо). Т.е. отсюда растёт требования поддержания билд-среды в идеальном соответствии продакшену — тоже потенциальная головная боль админа.
                    3) докер-контейнер в котором всё собирается и из которого потом вышвырнуто всё лишнее. Этим путём мы и пошли.


  1. AmdY
    28.10.2016 15:22

    Object.assign не имеет отношение к иммутабельности, он копирует объекты, да ещё по своим витиеватым правилам, советую быть очень осторожным с ним. https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


    1. justboris
      28.10.2016 16:11

      Если не забывать передавать пустой объект первым аргументом, то все иммутабельно, разве нет?


      1. AmdY
        28.10.2016 16:35
        +1

        Нет, он совсем не про то. Даже если вы просто копируете объект через assign, то получаете его уже мутированную копию
        >> Метод Object.assign() копирует из исходных объектов в целевой объект только перечисляемые и собственные свойства. Он использует внутренний метод [[Get]] на исходных объектах и внутренний метод [[Put]] на целевом объекте, так что он также вызывает геттеры и сеттеры.

        Во вторых, если у объекта есть вложенные объекты и вы их меняете, то мутирует и исходный объект.


      1. babichss
        28.10.2016 18:17

        Нет, он копирует ссылки на свойства, а не клонирует их. Потому для глубокого клонирования он не походит.


  1. to0n1
    28.10.2016 17:15

    еще есть замена копированию свойств объекта, и их переопределения

    const oldObj = {a: 1, b: 2, c: 3};
    const newObj = {...oldObj, c: '3a', d: 4};
    
    console.log(newObj); // {a: 1, b: 2, c: '3a', d: 4};
    


    1. justboris
      28.10.2016 17:36

      Это лишь proposal, пусть даже и stage-3, но не часть ES6.


  1. TheShock
    28.10.2016 17:16
    +3

    {в оригинале здесь была какая-то непонятная гифка с обезьяной, которую я как-то не очень понял, оттого и не буду её здесь ставить}

    Как на меня — потому что гифка обрезана. Обезьяне показали фокус и она очень удивилась. Уверен, автор имел ввиду, что мы удивимся его трюкам в статьях точно так же, как обезьяна на видео:

    Полное видео с обезьяной


    1. TheShock
      28.10.2016 17:26
      +3

      С деструктуризацией они облажались, кстати, по полной. В импорте сделали более удобную деструктуризацию через as, но внесли этим неконсистентность.

      import { member as alias } from "module-name";
      
      // vs
      
      const { first: second } = { first: 3 };
      


      В идеале им бы сейчас спохватиться и ввести дополнительный алиас для деструктуризации объекта, а старый оставить как депрекейтед:

      const { first as second } = { first: 3 };
      


      Тем более из-за этих их двоеточий нельзя нормально типизировать во Flow и TS:

      function ({ node: TreeNode }) // Фиг там
      


      В Flow рекомендуется что-то вроде:
      function ({ node }: { node: TreeNode })
      


      Но это ведь ужасно, все удобство деструктуризации пропадает. Кому интересно — есть issue с кучей комментов в Гитхабе Flow.


      1. Large
        30.10.2016 00:13
        +1

        Для таких случаев лучше тип определять на весь объект свойств иначе и правда уродски выглядит.


    1. Keyten
      29.10.2016 13:11
      +1

      Оффтоп, конечно, но добавлю


  1. Galy4a
    28.10.2016 18:18

    const original = [0,1,2,3];
    const copy = Object.assign([], original, { 2: 42 }); // [0,1,42,3]

    const copy = {...original, {2:42}};


    1. Igelko
      29.10.2016 12:07

      и это тоже, насколько я понимаю лишь shallow-copy =(


  1. Rulur
    28.10.2016 18:18

    Про «какая-то непонятная гифка с обезьяной». Это гифка сделана из видео как объезьяне показывали фокус и ее реакция на это. Гифка прицеплена к слову трюк в заголовке


    1. saggid
      28.10.2016 18:19

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


  1. Igelko
    29.10.2016 12:05
    +1

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


    function makePrefix(...prefix) {
        return (f, ...args) => f(...prefix, ...args);
    }
    
    const prefix = makePrefix(parameter1, parameter2, parameter3);
    ...
    prefix(db.orderAssignment.create, parameter4, parameter5)

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


    def f(a, b, c):
      ...
    
    f(a=2, c=4, b=3)

    Могу сказать, что это очень сильно улучшает читаемость кода.


  1. Finesse
    30.10.2016 02:13

    в оригинале здесь была какая-то непонятная гифка с обезьяной, которую я как-то не очень понял, оттого и не буду её здесь ставить

    В английском языке есть выражение «code monkey» (дословно переводится «кодовая обезьяна»), которое эквивалентно русскому «быдлокодер». Поэтому для англоговорящих гифка как раз в тему.


  1. afschr
    01.11.2016 03:30
    +1

    Правда, такой подход не очень рекомендуют использовать в официальной документации к React.js — прим. переводчика.

    Думаю, скорее не рекомендуется делать так:


    render () {
      const props = this.props
      return <SomeComponent {...props} />
    }

    Потому, что это:


    ...make your code messy by making it easy to pass a lot of irrelevant props to components...

    то есть, чтобы не засорять компонент props не относящимися к SomeComponent.


    1. saggid
      01.11.2016 07:16
      +1

      Да, всё так, но я всё равно решил упомянуть об этом в статье. Лишним не будет, думаю)