Руководство по javascript, часть 2: стиль кода и структура программ

reduce/reduceRight

Метод «arr.reduce(callback)» используется для последовательной обработки каждого элемента массива с сохранением промежуточного результата.

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

Метод используется для вычисления на основе массива какого-либо единого значения, иначе говорят «для свёртки массива». Чуть далее мы разберём пример для вычисления суммы.

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

Аргументы функции :

  • – последний результат вызова функции, он же «промежуточный результат».
  • – текущий элемент массива, элементы перебираются по очереди слева-направо.
  • – номер текущего элемента.
  • – обрабатываемый массив.

Кроме , методу можно передать «начальное значение» – аргумент . Если он есть, то на первом вызове значение будет равно , а если у нет второго аргумента, то оно равно первому элементу массива, а перебор начинается со второго.

Проще всего понять работу метода на примере.

Например, в качестве «свёртки» мы хотим получить сумму всех элементов массива.

Вот решение в одну строку:

Разберём, что в нём происходит.

При первом запуске – исходное значение, с которого начинаются вычисления, равно нулю (второй аргумент ).

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

Поток вычислений получается такой

В виде таблицы где каждая строка – вызов функции на очередном элементе массива:

результат
первый вызов
второй вызов
третий вызов
четвёртый вызов
пятый вызов

Как видно, результат предыдущего вызова передаётся в первый аргумент следующего.

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

Посмотрим, что будет, если не указать в вызове :

Результат – точно такой же! Это потому, что при отсутствии в качестве первого значения берётся первый элемент массива, а перебор стартует со второго.

Таблица вычислений будет такая же, за вычетом первой строки.

Метод arr.reduceRight работает аналогично, но идёт по массиву справа-налево.

1.3 Вещественные типы

Среди примитивных типов также есть два вещественных. Хотя это не совсем точное название. Официально они называются числа с плавающей точкой — floating point numbers. Название происходит из стандарта, когда целую и дробную часть числа разделяет точка (а не запятая).

Полезно:

В каждой стране свои стандарты для записи чисел (внезапно!).

Многие из нас привыкли писать точки для разделения тысяч и запятую для отделения дробной части: например, мы бы записали так . А вот в США, где жили создатели Java, принят другой стандарт:

В Java есть два примитивных типа с плавающей точкой: и .

Как мы уже говорили ранее, эти типы внутри устроены специфическим образом: фактически внутри каждой переменной этих типов находится не одно число, а два:

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

Тип

Само название типа происходит от floating point number. Размер этого типа совсем небольшой — всего 4 байта (32 бита), но он может хранить значения от до . Под мантиссу отдается 24 бита, под экспоненту — 8 бит. Этот тип способен хранить всего 8 значащих цифр.

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

Пример:

Код Значение переменной

Как видите, основной недостаток этого типа — очень маленькое количество значащих цифр и потеря точности уже в восьмой цифре. Поэтому тип не сильно популярен среди Java-программистов.

Тип

Тип является стандартным типом с плавающей точкой. Его название происходит от double floating point. Его еще называют числом с плавающей точкой двойной точности. Все вещественные литералы по умолчанию имеют тип .

Этот тип занимает 8 байт памяти (64 бита) и может хранить значения от до . Важным моментом является то, что под его мантиссу отводится 53 бита, а остальные 11 – под экспоненту.

Это позволяет хранить 15-17 значащих цифр.

Пример:

Код Значение переменной

Такая точность, особенно в сравнении с типом , является определяющей: 99% всех операций с вещественными числами выполняются с типом .

Под экспоненту выделяется бит, что позволяет хранить степень десятки от до (степень двойки — от до ). Тип легко может хранить число с сотней нулей после запятой:

Код Значение переменной

Как бесплатно перенести свои любимые треки в Spotify, используя Javascript

Все любители музыки в России с нетерпением ждали выхода Spotify на наш рынок. Когда наконец это случилось, перед пользователями встала проблема переноса музыки из других сервисов. Лично у меня за годы накопилась огромная коллекция музыки на разных платформах: Яндекс.Музыка, ВКонтакте, личная коллекция на жёстком диске и облако на Яндекс.Диске.

Сначала я думал воспользоваться сервисами вроде Soundiiz и TuneMyMusic. Но вдохновившись статьёй об использовании Python в тех же целях, мне стало интересно решить эту задачку с помощью Javascript. Далее я опишу ряд простых шагов с исходным кодом, которые помогут перенести вашу музыку из разных источников в Spotify.

Другие технологии. Альтернативы javascript.

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

Java — по сравнению с javascript, java-applet’ы тяжелые, долго загружаются, но могут все. Они, как правило, используются там, где требуется почти-десктоп приложение. Очень сильно java’у потеснила технология Flash.

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

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

  • Мощные средства для создания сетевых соединений(сокеты)
  • Объекты для работы с мультимедиа: изображениями, аудио, видео
  • Внутреннее хранилище объектов, которые не посылаются на сервер при каждом запросе, как куки.
  • Удобные графические средства разработки для Flash

Ну и для баланса — недостатки, по сравнению с javascript.

  • Отдельный контейнер. Например, нельзя выделить участок текста, частично находящегося в контейнере Flash.
  • Плохо индексируется поисковиками. Поисковики ходят по HTML-ссылкам, но(пока?) не кликают по ссылкам внутри Flash-приложения.

Из Flash можно легко вызвать javascript. Наоборот — сложнее, но тоже возможно, поэтому целесообразно знать обе технологии и применять их вместе.

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

Пока они все далеки по распространенности от javascript и flash.

  • JavaFX — «легкая» надстройка над Java, будет работать только с Java на компьютере клиента.
  • XUL — язык описания интерфейсов, удобен если писать планируете только под Mozilla. Также используется для написания десктоп-приложений.
  • Silverlight — конкурент Flash от Microsoft на основе .NET. Другими OS, кроме Windows, поддерживается слабо. Не имеет широкого распространения.
  • vbscript — попытка Microsoft сделать подобие javascript на основе Visual Basic. Не развивается, сильно уступает по возможностям, и, как следствие — практически не используется в современном веб-программировании.

ИЛИ «||» находит первое истинное значение

Описанная выше логика соответствует традиционной. Теперь давайте поработаем с «дополнительными» возможностями JavaScript.

Расширенный алгоритм работает следующим образом.

При выполнении ИЛИ || с несколькими значениями:

Оператор выполняет следующие действия:

  • Вычисляет операнды слева направо.
  • Каждый операнд конвертирует в логическое значение. Если результат , останавливается и возвращает исходное значение этого операнда.
  • Если все операнды являются ложными (), возвращает последний из них.

Значение возвращается в исходном виде, без преобразования.

Другими словами, цепочка ИЛИ возвращает первое истинное значение или последнее, если такое значение не найдено.

Например:

Это делает возможным более интересное применение оператора по сравнению с «чистым, традиционным, только булевым ИЛИ».

  1. Получение первого истинного значения из списка переменных или выражений.

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

    С помощью :

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

  2. Сокращённое вычисление.

    Операндами могут быть как отдельные значения, так и произвольные выражения. ИЛИ вычисляет их слева направо. Вычисление останавливается при достижении первого истинного значения. Этот процесс называется «сокращённым вычислением», поскольку второй операнд вычисляется только в том случае, если первого недостаточно для вычисления всего выражения.

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

    В приведённом ниже примере не изменяется:

    Если бы первый аргумент имел значение , то приступил бы к вычислению второго и выполнил операцию присваивания:

    Присваивание – лишь один пример. Конечно, могут быть и другие побочные эффекты, которые не проявятся, если вычисление до них не дойдёт.

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

    В большинстве случаев лучше использовать «обычный» , чтобы облегчить понимание кода, но иногда это может быть удобно.

Изучаем хук useRef в React.js

Перевод

Доброго времени суток, друзья.
Представляю вашему вниманию перевод небольшой заметки про использование хука useRef в React.
Хук useState позволяет добавлять состояние в функциональные компоненты. Данный хук предоставляет возможность передавать значение, сохраняемое при повторном рендеринге страницы, а также интерфейс для обновления этого значения и принудительного запуска ререндеринга.

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

useState возвращает массив, в котором первым элементом является сохраненное значение, а вторым — функция, запускающая повторный рендеринг.
Нам нужен только первый элемент, поэтому мы добавляем . При запуске usePersistentValue мы получим объект, в свойстве которого будет содержаться сохраненное значение.
Рассмотрим пример.

Основы

XMLHttpRequest имеет два режима работы: синхронный и асинхронный.

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

Чтобы сделать запрос, нам нужно выполнить три шага:

  1. Создать .

  2. Инициализировать его.

    Этот метод обычно вызывается сразу после . В него передаются основные параметры запроса:

    • – HTTP-метод. Обычно это или .
    • – URL, куда отправляется запрос: строка, может быть и объект URL.
    • – если указать , тогда запрос будет выполнен синхронно, это мы рассмотрим чуть позже.
    • , – логин и пароль для базовой HTTP-авторизации (если требуется).

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

  3. Послать запрос.

    Этот метод устанавливает соединение и отсылает запрос к серверу. Необязательный параметр содержит тело запроса.

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

  4. Слушать события на , чтобы получить ответ.

    Три наиболее используемых события:

    • – происходит, когда получен какой-либо ответ, включая ответы с HTTP-ошибкой, например 404.
    • – когда запрос не может быть выполнен, например, нет соединения или невалидный URL.
    • – происходит периодически во время загрузки ответа, сообщает о прогрессе.

Вот полный пример. Код ниже загружает с сервера и сообщает о прогрессе:

После ответа сервера мы можем получить результат запроса в следующих свойствах :

Код состояния HTTP (число): , , и так далее, может быть в случае, если ошибка не связана с HTTP.
Сообщение о состоянии ответа HTTP (строка): обычно для , для , для , и так далее.
(в старом коде может встречаться как )
Тело ответа сервера.

Мы можем также указать таймаут – промежуток времени, который мы готовы ждать ответ:

Если запрос не успевает выполниться в установленное время, то он прерывается, и происходит событие .

URL с параметрами

Чтобы добавить к URL параметры, вида , и корректно закодировать их, можно использовать объект URL:

«var» обрабатываются в начале запуска функции

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

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

Т.е. этот код:

…Технически полностью эквивалентен следующему (объявление переменной перемещено в начало функции):

…И даже коду ниже (как вы помните, блочная область видимости игнорируется):

Это поведение называется «hoisting» (всплытие, поднятие), потому что все объявления переменных «всплывают» в самый верх функции.

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

Объявления переменных «всплывают», но присваивания значений – нет.

Это проще всего продемонстрировать на примере:

Строка состоит из двух действий:

  1. Объявление переменной
  2. Присвоение значения в переменную .

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

Поскольку все объявления переменных обрабатываются в начале функции, мы можем ссылаться на них в любом месте. Однако, переменные имеют значение до строки с присвоением значения.

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

ECMAScript

Стандарт (формальное описание синтаксиса и работы языка) javascript называется ECMAScript. На нем, кстати, основан не только javascript, но и несколько других языков, например ActionScript (Flash).

По ECMAScript есть спецификация, которая подробно описывает синтаксис, управляющие конструкции и базовые объекты языка.

Например, вот скрипт, который работает, используя только ECMAScript. Кстати, поэтому он будет работать и в других языках, основанных на ECMAScript, включая ActionScript:

var max = 5
try {
  for(var i=0; i<Number.POSITIVE_INFINITY; i++) {
    if (i>max) throw new Error("failed to reach the stars")
  }
} catch(e) { }

ECMAScript — и правда очень особенный язык. Особенно для тех, кто пришел из PHP, C, Java. В нем особым образом устроены объекты и функции.

Здесь мы пройдем по основным особенностям и отличиям языка.

Уникальность javascript

Прелесть и соль Javascript заключаются всего в нескольких пунктах.

  • Полная интеграция с браузером
  • Простые вещи делаются просто
  • Поддерживается почти везде

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

Например, такие технологии как ActiveX, VBScript, XUL — поддерживаются не в каждом браузере (не кросс-браузерны). Такие технологии как Flash, Silverlight, Java — не полностью интегрированы с браузером, работают в своем окружении.

Поэтому Javascript — уникальная технология, и таковой останется. Сейчас она развивается, создается язык Javascript 2 и новый интерпретатор.

Учите javascript.

Как всё устроено, Юникод

Глубокое погружение в тему

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

Если вы не планируете их поддерживать, эту секцию можно пропустить.

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

Но 16 битов — это 65536 комбинаций, так что на все символы этого, разумеется, не хватит. Поэтому редкие символы записываются двумя 16-битными словами — это также называется «суррогатная пара».

Длина таких строк — :

Обратите внимание, суррогатные пары не существовали, когда был создан JavaScript, поэтому язык не обрабатывает их адекватно!

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

и — два редких метода, правильно работающие с суррогатными парами, но они и появились в языке недавно. До них были только String.fromCharCode и str.charCodeAt. Эти методы, вообще, делают то же самое, что , но не работают с суррогатными парами.

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

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

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

В данном случае:

Дальше в главе Перебираемые объекты будут ещё способы работы с суррогатными парами. Для этого есть и специальные библиотеки, но нет достаточно широко известной, чтобы предложить её здесь.

Во многих языках есть символы, состоящие из некоторого основного символа со знаком сверху или снизу.

Например, буква — это основа для . Наиболее используемые составные символы имеют свой собственный код в таблице UTF-16. Но не все, в силу большого количества комбинаций.

Чтобы поддерживать любые комбинации, UTF-16 позволяет использовать несколько юникодных символов: основной и дальше один или несколько особых символов-знаков.

Например, если после добавить специальный символ «точка сверху» (код ), отобразится Ṡ.

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

Например, если добавить символ «точка снизу» (код ), отобразится S с точками сверху и снизу: .

Добавляем два символа:

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

Например:

Для решения этой проблемы есть алгоритм «юникодной нормализации», приводящий каждую строку к единому «нормальному» виду.

Его реализует метод str.normalize().

Забавно, но в нашем случае «схлопывает» последовательность из трёх символов в один: — S с двумя точками.

Разумеется, так происходит не всегда. Просто Ṩ — это достаточно часто используемый символ, поэтому создатели UTF-16 включили его в основную таблицу и присвоили ему код.

Подробнее о правилах нормализации и составлении символов можно прочитать в дополнении к стандарту Юникод: Unicode Normalization Forms. Для большинства практических целей информации из этого раздела достаточно.

Комментарии

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

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

Однострочные комментарии начинаются с двойной косой черты .

Часть строки после считается комментарием. Такой комментарий может как занимать строку целиком, так и находиться после инструкции.

Как здесь:

Многострочные комментарии начинаются косой чертой со звёздочкой и заканчиваются звёздочкой с косой чертой .

Как вот здесь:

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

Это бывает удобно для временного отключения участка кода:

Используйте горячие клавиши!

В большинстве редакторов строку кода можно закомментировать, нажав комбинацию клавиш Ctrl+/ для однострочного комментария и что-то, вроде Ctrl+Shift+/ – для многострочных комментариев (выделите кусок кода и нажмите комбинацию клавиш). В системе Mac попробуйте Cmd вместо Ctrl.

Вложенные комментарии не поддерживаются!

Не может быть внутри .

Такой код «умрёт» с ошибкой:

Не стесняйтесь использовать комментарии в своём коде.

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

Позже в учебнике будет глава Качество кода, которая объяснит, как лучше писать комментарии.

Инкремент/декремент

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

Для этого существуют даже специальные операторы:

  • Инкремент увеличивает на 1:

  • Декремент уменьшает на 1:

Важно:

Инкремент/декремент можно применить только к переменной. Попытка использовать его на значении, типа 5++, приведёт к ошибке.

Операторы и могут быть расположены не только после, но и до переменной.

  • Когда оператор идёт после переменной – это «постфиксная форма»: .
  • «Префиксная форма» – это когда оператор идёт перед переменной: .

Обе эти формы записи делают одно и то же: увеличивают на .

Есть ли разница между ними? Да, но увидеть её мы сможем, только если будем использовать значение, которое возвращают .

Давайте проясним этот момент. Как мы знаем, все операторы возвращают значение. Операторы инкремент/декремент не исключение. Префиксная форма возвращает новое значение, в то время как постфиксная форма возвращает старое (до увеличения/уменьшения числа).

Чтобы увидеть разницу, вот небольшой пример:

В строке префиксная форма увеличения , она возвращает новое значение . Так что покажет .

Теперь посмотрим на постфиксную форму:

В строке постфиксная форма также увеличивает , но возвращает старое значение (которое было до увеличения). Так что покажет .

Подведём итоги:

  • Если результат оператора не используется, а нужно только увеличить/уменьшить переменную – без разницы, какую форму использовать:

  • Если хочется тут же использовать результат, то нужна префиксная форма:

  • Если нужно увеличить и при этом получить значение переменной до увеличения – постфиксная форма:

Инкремент/декремент можно использовать в любых выражениях

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

Например:

Сравните с:

Хотя технически всё в порядке, такая запись обычно делает код менее читабельным. Одна строка выполняет множество действий – нехорошо.

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

Лучше использовать стиль «одна строка – одно действие»:

Поиск подстроки

Существует несколько способов поиска подстроки.

Первый метод — str.indexOf(substr, pos).

Он ищет подстроку в строке , начиная с позиции , и возвращает позицию, на которой располагается совпадение, либо при отсутствии совпадений.

Например:

Необязательный второй аргумент позволяет начать поиск с определённой позиции.

Например, первое вхождение — на позиции . Для того, чтобы найти следующее, начнём поиск с позиции :

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

Тот же алгоритм можно записать и короче:

Также есть похожий метод str.lastIndexOf(substr, position), который ищет с конца строки к её началу.

Он используется тогда, когда нужно получить самое последнее вхождение: перед концом строки или начинающееся до (включительно) определённой позиции.

При проверке в условии есть небольшое неудобство. Такое условие не будет работать:

Мы ищем подстроку , и она здесь есть, прямо на позиции . Но не показывается, т. к. возвращает , и решает, что тест не пройден.

Поэтому надо делать проверку на :

Существует старый трюк с использованием — . Он преобразует число в 32-разрядное целое со знаком (signed 32-bit integer). Дробная часть, в случае, если она присутствует, отбрасывается. Затем все биты числа инвертируются.

На практике это означает простую вещь: для 32-разрядных целых чисел значение равно .

В частности:

Таким образом, равняется 0 только при (для любого , входящего в 32-разрядные целые числа со знаком).

Соответственно, прохождение проверки означает, что результат отличен от , совпадение есть.

Это иногда применяют, чтобы сделать проверку компактнее:

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

Просто запомните: означает «если найдено».

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

На данный момент такой трюк можно встретить только в старом коде, потому что в новом он просто не нужен: есть метод (см. ниже).

Более современный метод str.includes(substr, pos) возвращает , если в строке есть подстрока , либо , если нет.

Это — правильный выбор, если нам необходимо проверить, есть ли совпадение, но позиция не нужна:

Необязательный второй аргумент позволяет начать поиск с определённой позиции:

Методы str.startsWith и str.endsWith проверяют, соответственно, начинается ли и заканчивается ли строка определённой строкой:

Разбор худшего в мире куска кода

Перевод

Есть одна итальянская страница на Facebook. Называется она «Il Programmatore di Merda», что в переводе означает «Дерьмовый программист». Мне нравится эта страница.
Там часто публикуют куски отвратительного кода и мемы о программировании. Но однажды я увидел там кое-что совершенно потрясающее.
Этот кусок кода заслужил почётное звание «лучшего произведения» за неделю.
Я решил этот код разобрать, но тут так много всего неправильного, что мне сложно даже выбрать первую проблему для анализа.
Если вы — начинающий программист, то мой материал поможет вам понять то, какие ужасные ошибки совершены тем, кто писал этот код.

Операторы

JavaScript поддерживает следующие операторы:

Арифметические

Простые , а также деление по модулю и возведение в степень .

Бинарный плюс объединяет строки. А если одним из операндов является строка, то второй тоже будет конвертирован в строку:

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

Простые и составные .

Битовые операции

Битовые операторы работают с 32-битными целыми числами на самом низком, побитовом уровне. Подробнее об их использовании можно прочитать на ресурсе MDN.

Условный оператор

Единственный оператор с тремя параметрами: . Если условие истинно, возвращается , иначе – .

Логические операторы

Логические И , ИЛИ используют так называемое «ленивое вычисление» и возвращают значение, на котором оно остановилось (не обязательно или ). Логическое НЕ конвертирует операнд в логический тип и возвращает инвертированное значение.

Сравнение

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

Другие операторы сравнения тоже конвертируют значения разных типов в числовой тип.

Оператор строгого равенства не выполняет конвертирования: разные типы для него всегда означают разные значения.

Значения и особенные: они равны только друг другу, но не равны ничему ещё.

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

Другие операторы

Существуют и другие операторы, такие как запятая.

Подробности: Операторы, Операторы сравнения, Логические операторы.

Чего НЕ может JavaScript в браузере?

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

Примеры таких ограничений включают в себя:

  • JavaScript на веб-странице не может читать/записывать произвольные файлы на жёстком диске, копировать их или запускать программы. Он не имеет прямого доступа к системным функциям ОС.

    Современные браузеры позволяют ему работать с файлами, но с ограниченным доступом, и предоставляют его, только если пользователь выполняет определённые действия, такие как «перетаскивание» файла в окно браузера или его выбор с помощью тега .

    Существуют способы взаимодействия с камерой/микрофоном и другими устройствами, но они требуют явного разрешения пользователя. Таким образом, страница с поддержкой JavaScript не может незаметно включить веб-камеру, наблюдать за происходящим и отправлять информацию в ФСБ.

  • Различные окна/вкладки не знают друг о друге. Иногда одно окно, используя JavaScript, открывает другое окно. Но даже в этом случае JavaScript с одной страницы не имеет доступа к другой, если они пришли с разных сайтов (с другого домена, протокола или порта).

    Это называется «Политика одинакового источника» (Same Origin Policy). Чтобы обойти это ограничение, обе страницы должны согласиться с этим и содержать JavaScript-код, который специальным образом обменивается данными.

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

  • JavaScript может легко взаимодействовать с сервером, с которого пришла текущая страница. Но его способность получать данные с других сайтов/доменов ограничена. Хотя это возможно в принципе, для чего требуется явное согласие (выраженное в заголовках HTTP) с удалённой стороной. Опять же, это ограничение безопасности.

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

Языки «над» JavaScript

Синтаксис JavaScript подходит не под все нужды. Разные люди хотят иметь разные возможности.

Это естественно, потому что проекты разные и требования к ним тоже разные.

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

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

Примеры таких языков:

  • CoffeeScript добавляет «синтаксический сахар» для JavaScript. Он вводит более короткий синтаксис, который позволяет писать чистый и лаконичный код. Обычно такое нравится Ruby-программистам.
  • TypeScript концентрируется на добавлении «строгой типизации» для упрощения разработки и поддержки больших и сложных систем. Разработан Microsoft.
  • Flow тоже добавляет типизацию, но иначе. Разработан Facebook.
  • Dart стоит особняком, потому что имеет собственный движок, работающий вне браузера (например, в мобильных приложениях). Первоначально был предложен Google, как замена JavaScript, но на данный момент необходима его транспиляция для запуска так же, как для вышеперечисленных языков.

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

JavaScript, Python или Go: что лучше всего подойдёт для бэкенд-разработки в 2021 году?

Перевод

Уже прошло почти восемь месяцев 2020 года, а технические прогнозы на этот год всё выходят и выходят. И это — несмотря на то, что очень сложно предсказать будущее в такой динамично развивающейся индустрии, как разработка программного обеспечения. Тот, кто работает в этой индустрии, видел, как технологии приходят и уходят. Иногда эти технологии проводят свою недолгую жизнь практически незаметно. Технологиям нелегко выживать в мире программирования.
Но если вспомнить прошлое, окажется, что языки программирования имеют огромную историю. В их истории было множество заметных событий, оказавших серьёзное влияние на индустрию. Например, C и Java, одни из самых старых языков программирования, до сих пор находят широкое применение. Но если поинтересоваться их популярностью, окажется, что сейчас они занимают не самые высокие позиции.
Я — программист. Мне очень нравится JavaScript (у меня с этим языком, так сказать, «вечная связь»), я пишу на этом языке уже давно. Но если немного оглядеться, то можно заметить, что в мире разработки ПО есть и другие языки. Предлагаю поразмыслить о том, что лучше использовать для серверной разработки в 2021 году: JavaScript, Python или Go. Но, прежде чем говорить о сильных сторонах каждого из этих языков, давайте взглянем на результаты некоторых исследований.