Мы не будем заострять внимание на востребованности JS. Чтобы понять, о чем пойдет речь, предлагаем ознакомиться со статьями «JavaScript и то, что вы о нем не знали», а также «Перлы языка JavaScript».
Добавление RegExps
Знаете ли вы, что можете добавлять такие цифры?
- JavaScript спецификация 21.2.5.10. Получить RegExp.prototype.source
Функции вызова
Давайте объявим функцию, которая выводит все параметры в консоль:
Несомненно, вы знаете, что эту функцию можно вызвать следующим образом:
Но знаете ли вы, что можете вызвать любую функцию вот так?
Это вовсе не волшебство. В приведенном выше примере функция f является тегом для шаблонного литерала. Первый аргумент содержит массив строковых значений. Остальные аргументы связаны с выражениями. Пример:
Это волшебство знаменитой библиотеки под названием styled-components, столь популярной в сообществе React.
Ссылка на спецификацию:
- JavaScript спецификация 12.3.7 Tagged Templates
Вызов вызов вызов
Внимание, это может сломать вам голову! Попробуйте мысленно воспроизвести этот код: мы применяем метод call с помощью метода apply. Узнайте больше:
- JavaScript спецификация 19.2.3.3 Функция.prototype.call (thisArg, . args)
JavaScript спецификация: свойство конструктора
Давайте рассмотрим этот пример шаг за шагом:
Object.prototype.constructor возвращает ссылку на функцию-конструктор объекта, которая создала объект экземпляра. В случае со строками – это строка, в случае с числами – это число и т. д.
- на MDN
- JavaScript спецификация 19.1.3.1 Object.prototype.constructor
Объект как ключ к свойствам объекта
Почему это так работает? Здесь мы используем вычисленное имя объекта. Когда вы передаете объект между этими скобками, получаете ключ свойства ‘[object Object]’ и значение <>.
Мы можем сделать следующим образом:
Подробнее об объектных читайте здесь:
- на MDN
- JavaScript спецификация 12.2.6 Инициализатор объектов
Доступ к прототипам с помощью __proto__
Порой JavaScript элементы поражают. Как мы знаем, примитивы не имеют прототипов. Но если мы попытаемся получить значение примитивов __proto__, мы получим следующее:
Это происходит потому, что, когда что-то не имеет прототипа, оно будет завернуто в оболочку с использованием метода ToObject. Итак, шаг за шагом:
Вот более подробная информация о __proto__:
Каков результат приведенного ниже выражения?
Мы определили объект со свойством Object, используя Shorthand property notation:
Затем мы передали этот объект в шаблонный литерал, так что метод toString вызывает данный объект. Вот почему мы получаем строку ‘[object Object]’.
- JavaScript спецификация 12.2.9 Шаблонные литералы на MDN
Деструктурирование со значениями по умолчанию
Рассмотрим этот пример:
Отличная задача для собеседования. Какое значение y? Ответ:
В приведенном выше примере:
- Мы объявляем x без значения, поэтому он не определен.
- Затем мы упаковываем значение x в свойство объекта x.
- Затем мы извлекаем значение x, используя деструктурирование, и хотим назначить его y. Если значение не определено, мы будем использовать 1 в качестве значения по умолчанию.
- Возвращаем значение y.
- на MDN
Такие JavaScript элементы, как точки и их расширение
Интересные примеры могут быть составлены с расширением массивов. Учтем это:
Почему 3? Когда мы используем оператор расширения, вызывается метод @@iterator, и возвращаемый итератор используется для получения значений, которые нужно повторить. По умолчанию итератор для строки расширяет строку символами. После расширения мы собираем эти символы в массив. Затем мы снова расширяем данный массив и снова упаковываем его в массив.
Строка ‘. ‘ состоит из трех точек (символов), поэтому длина результирующего массива равна трем.
Теперь, шаг за шагом:
Очевидно, что мы можем распределять элементы массива столько раз, сколько хотим:
Labels
Не так много программистов знают о метках в JavaScript. Они интересны:
Обозначенная инструкция используется с операторами break или continue. Вы можете применить метку для идентификации цикла, а затем использовать break или continue, чтобы указать, должна ли программа прерывать цикл или продолжать его выполнение.
В приведенном выше примере мы идентифицируем метку foo. После этого выполняется console.log (‘first’); , а затем мы прерываем выполнение.
JavaScript элементы «метки»:
Вложенные ярлыки
Как и в предыдущих примерах, следуйте по этим ссылкам:
Коварный try..catch
Что именно должно вернуться, исходя из приведенного ниже примера? 2 или 3?
Ответ 3. Удивлены?
Относится ли это к множественному наследованию?
Некоторые JavaScript элементы заставляют серьезно поразмыслить. Взгляните на представленный код:
Является ли это множественным наследованием? Нет.
Значение extends ((String, Array)) представляет собой любопытную часть кода. Оператор группировки всегда возвращает свой последний аргумент, поэтому (String, Array) – это на самом деле просто Array. Значит, мы создали класс, который просто наследует массив.
Генератор
Рассмотрим пример генератора:
Как вы можете видеть, возвращаемое значение – это объект со значением, равным f. В данном случае мы можем сделать что-то вроде этого:
Предлагаем к прочтению такие разделы спецификации:
Класс класса
И снова JavaScript элементы ведут себя вне законов логики. Рассмотрим запутанный синтаксис:
Кажется, мы объявляем класс внутри класса. Должны быть и ошибки, однако, мы получаем строку ‘object’.
Начиная с эпохи ECMAScript 5, ключевые слова допускаются как имена свойств. Поэтому подумайте об этом простом примере:
И ES6 стандартизовал сокращенные определения методов. Кроме того, классы могут быть анонимными. Поэтому, если мы отбросим : function, то получим:
Результат класса по умолчанию всегда является простым объектом. И его typeof должно возвращать ‘object’.
Non-coercible objects
С известными символами есть способ избавиться от принуждения типа JS. Взгляните:
Теперь мы можем использовать это следующим образом:
Запутанные стрелочные функции
Рассмотрим приведенный ниже пример:
Хорошо, хорошо, но что насчет этого?
Вы можете ожидать <> вместо undefined. Это связано с тем, что фигурные скобки являются частью синтаксиса стрелочных функций, поэтому f вернется undefined.
Трудное возвращение
С return тоже не все так чисто. Учтите данный нюанс:
Дело в том, что return и возвращаемое выражение должны находиться в одной строке:
Доступ к свойствам объекта с использованием массивов
Такие JavaScript элементы как массивы заслуживают отдельного раздела «необъяснимо, но факт». Тем не менее, затронем мы их здесь:
Как насчет псевдо-многомерных массивов?
Оператор скобок [] преобразует выражение, переданное toString. Преобразование одноэлементного массива в строку – это такое же преобразование элемента в строку: