JavaScript: 7 полезных мелочей

Автор оригинала: David Walsh
  • Перевод
Автор заметки, перевод которой мы сегодня публикуем, говорит, что в JavaScript, как и в любом другом языке программирования, можно обнаружить множество маленьких хитростей, предназначенных для решения самых разных задач, как простых, так и довольно сложных. Некоторые из подобных приёмов широко известны, а другие, не такие распространённые, могут приятно удивить тех, кто о них не знает. Сейчас мы рассмотрим 7 полезных приёмов программирования на JavaScript.



1. Получение уникальных значений массива


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

var j = [...new Set([1, 2, 3, 3])]
// [1, 2, 3]

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

2. Массивы и логические значения


Вам когда-нибудь нужно было убрать из массива значения, приведение которых к логическому типу даёт false? Например, это такие значения, как 0, undefined, null, false. Возможно, вы не знали, что для того, чтобы это сделать, можно поступить так:

myArray
    .map(item => {
        // ...
    })
    // Избавляемся от ненужных значений
    .filter(Boolean);

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

3. Создание по-настоящему пустых объектов


Уверен в том, что вы можете создать объект, который кажется пустым, воспользовавшись синтаксисом объектного литерала: {}. Но такому объекту будет назначен прототип (__proto__), у него будет метод hasOwnProperty() и другие методы объектов. Для того чтобы создать по-настоящему пустой объект, который можно, например, использовать в качестве «словаря», можно поступить так:

let dict = Object.create(null);

// dict.__proto__ === "undefined"
// У объекта нет никаких свойств до тех пор, пока вы их в явном виде не добавите к нему

В объекте, созданном таким способом, нет свойств и методов, которые не добавлены в него самим программистом.

4. Слияние объектов


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

const person = { name: 'David Walsh', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };

const summary = {...person, ...tools, ...attributes};
/*
Object {
  "computer": "Mac",
  "editor": "Atom",
  "eyes": "Blue",
  "gender": "Male",
  "hair": "Brown",
  "handsomeness": "Extreme",
  "name": "David Walsh",
}
*/

Оператор ... значительно упрощает решение задачи слияния объектов.

5. Обязательные параметры функций


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

const isRequired = () => { throw new Error('param is required'); };

const hello = (name = isRequired()) => { console.log(`hello ${name}`) };

// Тут будет выдана ошибка, функции не передан аргумент name
hello();

// Здесь тоже будет ошибка
hello(undefined);

// Эти варианты вызова функции будут работать нормально
hello(null);
hello('David');

Перед нами — дополнительный уровень проверки того, что передаётся функциям.

6. Деструктурирующее присваивание и новые имена извлечённых свойств объектов


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

const obj = { x: 1 };

// Теперь мы можем работать с obj.x как с x
const { x } = obj;

// А теперь obj.x для нас выглядит как otherName
const { x: otherName } = obj;

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

7. Разбор строк запросов


Многие годы мы, для разбора строк запросов, писали регулярные выражения, но эти времена прошли. Теперь для решения этой задачи можно воспользоваться замечательным API URLSearchParams:

// Предполагается, что мы работаем с "?post=1234&action=edit"

var urlParams = new URLSearchParams(window.location.search);

console.log(urlParams.has('post')); // true
console.log(urlParams.get('action')); // "edit"
console.log(urlParams.getAll('action')); // ["edit"]
console.log(urlParams.toString()); // "?post=1234&action=edit"
console.log(urlParams.append('active', '1')); // "?post=1234&action=edit&active=1"

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

Итоги


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

Уважаемые читатели! Знаете какие-нибудь полезные приёмы JS-программирования? Если так — просим ими поделиться.

RUVDS.com
979,98
RUVDS – хостинг VDS/VPS серверов
Поделиться публикацией

Похожие публикации

Комментарии 18

    –4

    Можно выделить только URLSearchParams, остальное — без комментариев. Очень полезные мелочи — деструктурирующее присваивание и spread-оператор, только не мелочи, и не полезные, а обязательные к использованию. Ну, про обязательные параметры вообще молчу — имхо, я бы гнал "программистов", которые такое практикуют, ссаными тряпкями.


    Улыбнуло про пустые объекты — в js и так нормального ооп нету (особенности интерпретации — все, сюрприз, превращается в функциональщину и императивщину).


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


    Продолжайте переводить подобный кал, не обращая внимания на то, что переводите. Удачи.

      +6
      Очень полезные мелочи — деструктурирующее присваивание и spread-оператор, только не мелочи, и не полезные, а обязательные к использованию.

      Всегда приятно смотреть на то, как приходит новый программист на ES6, и первым делом подключает lodash, потому что ему видите ли надо пару объектов слить вместе, а руками он не умеет ^_^
      Но вообще деструктурирующее присваивание — это «мелкий» сахар, в том плане, что я бы его обязательным не назвал. С ним красивше, но без него тоже читаемо. А вот spread — это «глубокий» сахар, с его помощью сокращаются целые блоки унылого кода по переприсвоению; и читать код от того, кто его просто не знает — иногда очень мучительно.
        0
        Совершенно с вами согласен. У меня только один вопрос к ru_vds: каким образом подобная чушь, под которой куча гневных комментариев:

        1) Набирает 10-15+ рейтинга
        2) Практически все отрицательные (по отношению к содержимому статьи) комментарии в диких минусах.

        При этом всем, в их недавнем посте про консоли в комментах были ссылки на 3 (3, Карл!) поста с практически ИДЕНТИЧНЫМ содержимым.

        *негодует*
          0

          Вот пока эти переводы набирают 10-15 плюсов рейтинга, ru_vds будет публиковать эти унылые статьи.

            0
            Если вам не понравилась какая-то публикация, то вы в праве поставить ей минус. Но будет гораздо лучше и полезней для читателей Хабра, если вы пришлёте нам какую-нибудь действительно крутую (по вашему мнению) публикацию, которую мы бы перевели (можно в личку).
      –2
      Одна половина советов из 2015, за другую вас погонят тряпками из компании
        –3
        сомневаюсь, что применяют isRequired() на практике. для простой проверки количества параметров проще arguments.length, а для проверки, что в параметре есть что-то осмысленное, нужен как минимум typeof.
          +1
          Если дошло до isRequired не пора ли посмотреть в сторону статанализа, тайпчекеров и вообще компиляторов статически типизированных языков в JS?
            +4

            С isRequired — приём не для прода, но забавный, стоит запомнить, пожалуй (и да, статическая типизация — не панацея, хотя я сам пишу на TypeScript). Остальное… вот кто из более-менее освоившихся в теме этого не знает, скажите на милость (кроме filter(Boolean), которое с непривычки выглядит как адский хак)?

              –2
              Оператор… значительно

              Не устану нести свет людям: это не оператор в его классическом понимании, а синтаксис.

              myArray
              .map(item => {
              //…
              })
              // Избавляемся от ненужных значений
              .filter(Boolean);


              связку map и filter можно заменить, на один reduce:

              […].reduce((prev, curr) => {
              const tmp = /*cast to boolean*/
              return tmp && prev
              }, true)
                +2
                А последнее, извиняюсь, каким образом? map + filter возвращает массив, reduce в таком исполнении — boolean.
                  –1
                  это магия js ;))))))
                  [1,2,3].reduce((acc, cur)=>cur%2?acc.concat([cur*3]):acc, [])
                    0
                    Нет, про этот-то приём я знаю, я пытался понять, что хотел сказать автор предыдущего комментария своей конструкцией.
                      0
                      наверное что-нибудь типа reduce = filter + map:
                      [0,null,1,2,false,3].reduce((acc, cur)=>Boolean(cur)?acc.concat([cur*3]):acc, [])

                      может просто написал неправильно
                      хотя так вот короче и понятнее:
                      [0,null,1,2,false,3].filter(Boolean).map(i=>i*3)

                      но 2 прогона =(((
                      в этом смысле итераторы питона лучше =)
                        0
                        Я просто немного поспешил с ответом. В своей практике я часто привожу массив вида [true, false, true] к переменной в которой хранится показатель того, что все объекты в изначальном массиве содержат нужное свойство или нужное значение у этого свойства
                  0
                  Благодарю за статью
                    0
                    К
                    Деструктурирующее присваивание и новые имена извлечённых свойств объектов
                    Я бы ещё добавил что это работает и с массивами.
                    let arr = [1,2,3,4];
                    let {0: first, 1: second} = arr;
                    
                      +3
                      А такой вариант —
                      let arr = [1, 2, 3, 4];
                      let [first, second] = arr;

                      чем хуже?

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

                    Самое читаемое