Базовые операторы, математика
Многие операторы знакомы нам ещё со школы: сложение + , умножение * , вычитание — и так далее.
В этой главе мы начнём с простых операторов, а потом сконцентрируемся на специфических для JavaScript аспектах, которые не проходят в школьном курсе арифметики.
Термины: «унарный», «бинарный», «операнд»
Прежде, чем мы двинемся дальше, давайте разберёмся с терминологией.
Операнд – то, к чему применяется оператор. Например, в умножении 5 * 2 есть два операнда: левый операнд равен 5 , а правый операнд равен 2 . Иногда их называют «аргументами» вместо «операндов».
Унарным называется оператор, который применяется к одному операнду. Например, оператор унарный минус "-" меняет знак числа на противоположный:
Бинарным называется оператор, который применяется к двум операндам. Тот же минус существует и в бинарной форме:
Формально, в последних примерах мы говорим о двух разных операторах, использующих один символ: оператор отрицания (унарный оператор, который обращает знак) и оператор вычитания (бинарный оператор, который вычитает одно число из другого).
Математика
Поддерживаются следующие математические операторы:
- Сложение + ,
- Вычитание — ,
- Умножение * ,
- Деление / ,
- Взятие остатка от деления % ,
- Возведение в степень ** .
Первые четыре оператора очевидны, а про % и ** стоит сказать несколько слов.
Взятие остатка %
Оператор взятия остатка % , несмотря на обозначение, никакого отношения к процентам не имеет.
Результат a % b – это остаток от целочисленного деления a на b .
Возведение в степень **
Оператор возведения в степень a ** b возводит a в степень b .
В школьной математике мы записываем это как a b .
Математически, оператор работает и для нецелых чисел. Например, квадратный корень является возведением в степень 1/2 :
Сложение строк при помощи бинарного +
Давайте рассмотрим специальные возможности операторов JavaScript, которые выходят за рамки школьной арифметики.
Обычно при помощи плюса ‘+’ складывают числа.
Но если бинарный оператор ‘+’ применить к строкам, то он их объединяет в одну:
Обратите внимание, если хотя бы один операнд является строкой, то второй будет также преобразован в строку.
Как видите, не важно, первый или второй операнд является строкой.
Вот пример посложнее:
Здесь операторы работают один за другим. Первый + складывает два числа и возвращает 4 , затем следующий + объединяет результат со строкой, производя действие 4 + ‘1’ = ’41’ .
Сложение и преобразование строк — это особенность бинарного плюса + . Другие арифметические операторы работают только с числами и всегда преобразуют операнды в числа.
Например, вычитание и деление:
Приведение к числу, унарный +
Плюс + существует в двух формах: бинарной, которую мы использовали выше, и унарной.
Унарный, то есть применённый к одному значению, плюс + ничего не делает с числами. Но если операнд не число, унарный плюс преобразует его в число.
На самом деле это то же самое, что и Number(. ) , только короче.
Необходимость преобразовывать строки в числа возникает очень часто. Например, обычно значения полей HTML-формы — это строки. А что, если их нужно, к примеру, сложить?
Бинарный плюс сложит их как строки:
Поэтому используем унарный плюс, чтобы преобразовать к числу:
С точки зрения математика, такое изобилие плюсов выглядит странным. Но с точки зрения программиста тут нет ничего особенного: сначала выполнятся унарные плюсы, которые приведут строки к числам, а затем бинарный ‘+’ их сложит.
Почему унарные плюсы выполнились до бинарного сложения? Как мы сейчас увидим, дело в их приоритете.
Приоритет операторов
В том случае, если в выражении есть несколько операторов – порядок их выполнения определяется приоритетом, или, другими словами, существует определённый порядок выполнения операторов.
Из школы мы знаем, что умножение в выражении 1 + 2 * 2 выполнится раньше сложения. Это как раз и есть «приоритет». Говорят, что умножение имеет более высокий приоритет, чем сложение.
Скобки важнее, чем приоритет, так что, если мы не удовлетворены порядком по умолчанию, мы можем использовать их, чтобы изменить приоритет. Например, написать (1 + 2) * 2 .
В JavaScript много операторов. Каждый оператор имеет соответствующий номер приоритета. Тот, у кого это число больше, – выполнится раньше. Если приоритет одинаковый, то порядок выполнения – слева направо.
Отрывок из таблицы приоритетов (нет необходимости всё запоминать, обратите внимание, что приоритет унарных операторов выше, чем соответствующих бинарных):
| Приоритет | Название | Обозначение |
|---|---|---|
| … | … | … |
| 15 | унарный плюс | + |
| 15 | унарный минус | — |
| 14 | возведение в степень | ** |
| 13 | умножение | * |
| 13 | деление | / |
| 12 | сложение | + |
| 12 | вычитание | — |
| … | … | … |
| 2 | присваивание | = |
| … | … | … |
Так как «унарный плюс» имеет приоритет 15 , который выше, чем 12 у «сложения» (бинарный плюс), то в выражении "+apples + +oranges" сначала выполнятся унарные плюсы, а затем сложение.
Присваивание
Давайте отметим, что в таблице приоритетов также есть оператор присваивания = . У него один из самых низких приоритетов: 2 .
Именно поэтому, когда переменной что-либо присваивают, например, x = 2 * 2 + 1 , то сначала выполнится арифметика, а уже затем произойдёт присваивание = с сохранением результата в x .
Присваивание = возвращает значение
Тот факт, что = является оператором, а не «магической» конструкцией языка, имеет интересные последствия.
Большинство операторов в JavaScript возвращают значение. Для некоторых это очевидно, например сложение + или умножение * . Но и оператор присваивания не является исключением.
Вызов x = value записывает value в x и возвращает его.
Благодаря этому присваивание можно использовать как часть более сложного выражения:
В примере выше результатом (a = b + 1) будет значение, которое присваивается переменной a (то есть 3 ). Потом оно используется для дальнейших вычислений.
Забавное применение присваивания, не так ли? Нам нужно понимать, как это работает, потому что иногда это можно увидеть в JavaScript-библиотеках.
Однако писать самим в таком стиле не рекомендуется. Такие трюки не сделают ваш код более понятным или читабельным.
Присваивание по цепочке
Рассмотрим ещё одну интересную возможность: цепочку присваиваний.
Такое присваивание работает справа налево. Сначала вычисляется самое правое выражение 2 + 2 , и затем результат присваивается переменным слева: c , b и a . В конце у всех переменных будет одно значение.
Опять-таки, чтобы код читался легче, лучше разделять подобные конструкции на несколько строчек:
Польза от такого стиля особенно ощущается при быстром просмотре кода.
Сокращённая арифметика с присваиванием
Часто нужно применить оператор к переменной и сохранить результат в ней же.
Основы JavaScript для начинающих разработчиков
Материал, перевод которого мы сегодня публикуем, посвящён основам JavaScript и предназначен для начинающих программистов. Его можно рассматривать и как небольшой справочник по базовым конструкциям JS. Здесь мы, в частности, поговорим о системе типов данных, о переменных, о массивах, о функциях, о прототипах объектов, и о некоторых других особенностях языка.
Примитивные типы данных
В JavaScript имеются следующие примитивные типы данных: number , boolean , string , undefined , null . Сразу нужно отметить, что, при работе с примитивными типами данных, например, со строковыми литералами, мы, даже не проводя явного преобразования, сможем обращаться к их методам и свойствам. Дело тут в том, что при попытке выполнения подобных операций литералы автоматически оснащаются соответствующей объектной обёрткой.
▍Числа
В JavaScript имеется лишь один тип чисел — это числа двойной точности с плавающей запятой. Это ведёт к тому, что результаты вычисления некоторых выражений арифметически неверны. Возможно, вы уже знаете, что в JS значение выражения 0.1 + 0.2 не равно 0.3 . В то же время, при работе с целыми числами таких проблем не наблюдается, то есть, 1 + 2 === 3 .
В JavaScript имеется объект Number , представляющий собой объектную обёртку для числовых значений. Объекты типа Number можно создавать либо используя команду вида var a = new Number(10) , либо можно полагаться на автоматическое поведение системы, описанное выше. Это, в частности, позволяет вызывать методы, хранящиеся в Number.prototype в применении к числовым литералам:
Существуют глобальные функции, предназначенные для преобразования значений других типов в числовой тип. Это — parseInt() , parseFloat() и конструкция Number() , которая в данном случае выступает в виде обычной функции, выполняющей преобразование типов:
Если в ходе операции с числами получается нечто, не являющееся числом (в ходе неких вычислений, или при попытке преобразования чего-либо в число), JavaScript не выдаст ошибку, а представит результат подобной операции в виде значения NaN (Not-a-Number, не число). Для того, чтобы проверить, является ли некое значение NaN , можно воспользоваться функцией isNaN() .
Арифметические операции JS работают вполне привычным образом, но надо обратить внимание на то, что оператор + может выполнять и сложение чисел, и конкатенацию строк.
▍Строки
Строки в JavaScript представляют собой последовательности символов Unicode. Строковые литералы создают, заключая текст, который нужно в них поместить, в двойные ( «» ) или одинарные ( » ) кавычки. Как уже было сказано, при работе со строковыми литералами мы можем полагаться на соответствующую объектную обёртку, в прототипе которой имеется множество полезных методов, среди них — substring() , indexOf() , concat() .
Строки, как и другие примитивные значения, иммутабельны. Например, метод concat() не модифицирует существующую строку, а создаёт новую.
▍Логические значения
Логический тип данных в JS представлен двумя значениями — true и false . Язык может автоматически преобразовывать различные значения к логическому типу данных. Так, ложными, помимо логического значения false , являются значения null , undefined , » (пустая строка), 0 и NaN . Всё остальное, включая любые объекты, представляет собой истинные значения. В ходе выполнения логических операций всё, что считается истинным, преобразуется к true , а всё, что считается ложным, преобразуется к false . Взгляните на следующий пример. В соответствии с вышеизложенными принципами пустая строка будет преобразована к false и в результате выполнения этого кода в консоль попадёт строка This is false .
Объекты
Объекты — это динамические структуры, состоящие из пар ключ-значение. Значения могут иметь примитивные типы данных, могут быть объектами или функциями.
Объекты проще всего создавать, используя синтаксис объектных литералов:
Свойства объекта можно, в любое время, читать, добавлять, редактировать и удалять. Вот как это делается:
- Чтение свойств: object.name, object[expression] .
- Запись данных в свойства (если свойство, к которому обращаются, не существует, добавляется новое свойство с указанным ключом): object.name = value , object[expression] = value .
- Удаление свойств: delete object.name , delete object[expression] .
Объекты в языке реализованы в виде хэш-таблиц. Простую хэш-таблицу можно создать, используя команду Object.create(null) :
Если объект нужно сделать иммутабельным, можно воспользоваться командой Object.freeze() .
Для перебора всех свойств объекта можно воспользоваться командой Object.keys() :
▍Сравнение значений примитивных типов и объектов
При практической работе с примитивными значениями можно, как уже было сказано, воспринимать их как объекты, у которых есть свойства и методы, хотя объектами они не являются. Примитивные значения иммутабельны, внутренняя структура объектов может меняться.
Переменные
В JavaScript переменные можно объявлять, используя ключевые слова var , let и const .
При использовании ключевого слова var можно объявить переменную, и, если надо — инициализировать её неким значением. Если переменная не инициализирована, её значением является undefined . Переменные, объявленные с использованием ключевого слова var , имеют функциональную область видимости.
Ключевое слово let очень похоже на var , разница заключается в том, что переменные, объявленные с ключевым словом let , имеют блочную область видимости.
Блочную область видимости имеют и переменные объявленные с помощью ключевого слова const , которые, учитывая то, что значения подобных переменных нельзя изменять, правильнее будет называть «константами». Ключевое слово const , которое «замораживает» значение переменной, объявленной с его использованием, можно сравнить с методом Object.freeze() , «замораживающим» объекты.
Если переменная объявлена за пределами какой-либо функции, её область видимости является глобальной.
Массивы
Массивы в JavaScript реализованы с использованием объектов. Как результат, говоря о массивах, мы, фактически, обсуждаем объекты, похожие на массивы. Работать с элементами массива можно, используя их индексы. Числовые индексы преобразуются в строки и используются как имена для доступа к значениям элементов массивов. Например, конструкция вида arr[1] аналогична конструкции вида arr[‘1’] , и та и другая дадут доступ к одному и тому же значению: arr[1] === arr[‘1’] . В соответствии с вышесказанным, простой массив, объявленный командой let arr = [‘A’, ‘B’, ‘C’] , представляется в виде объекта примерно следующего вида:
Удаление элементов массива с использованием команды delete оставляет в нём «дыры». Для того чтобы избежать этой проблемы, можно использовать команду splice() , но работает она медленно, так как, после удаления элемента, перемещает оставшиеся элементы массива, фактически, сдвигая их к началу массива, влево.
Методы массивов позволяют легко реализовывать такие структуры данных, как стеки и очереди:
Функции
Функции в JavaScript являются объектами. Функции можно назначать переменным, хранить в объектах или массивах, передавать в виде аргументов другим функциям и возвращать из других функций.
Существует три способа объявления функций:
- Классическое объявление функции (Function Declaration или Function Statement).
- Использование функциональных выражений (Function Expression), которые ещё называют функциональными литералами (Function Literal).
- Использование синтаксиса стрелочных функций (Arrow Function).
▍Классическое объявление функции
При таком подходе к объявлению функций действуют следующие правила:
- Первым ключевым словом в строке объявления функции является function .
- Функции необходимо назначить имя.
- Функцию можно использовать в коде, находящимся до её объявления благодаря механизму подъёма объявления функции в верхнюю часть области видимости, в которой она объявлена.
▍Функциональные выражения
При использовании функциональных выражений нужно учитывать следующее:
- Ключевое слово function уже не является первым словом в строке объявления функции.
- Наличие имени у функции необязательно. Возможно применение как анонимных, так и именованных функциональных выражений.
- Команды вызова таких функций должны следовать за командами их объявления.
- Такую функцию можно запустить сразу же после объявления, воспользовавшись синтаксисом IIFE (Immediately Invoked Function Expression — немедленно вызываемое функциональное выражение).
▍Стрелочные функции
Стрелочные функции, по сути, можно считать «синтаксическим сахаром» для создания анонимных функциональных выражений. Надо отметить, что у таких функций нет собственных сущностей this и arguments . Объявление стрелочной функции выглядит так:
▍Способы вызова функций
Функции можно вызывать различными способами.
Обычный вызов функции
Вызов функции в виде метода объекта
Вызов функции в виде конструктора
Вызов функции с использованием метода apply()
Вызов функции с использованием метода bind()
Функции можно вызывать с большим или меньшим количеством аргументов, чем то количество параметров, которое было задано при их объявлении. В ходе работы функции «лишние» аргументы будут просто проигнорированы (хотя у функции будет доступ к ним), отсутствующие параметры получат значение undefined .
У функций есть два псевдо-параметра: this и arguments .
▍Ключевое слово this
Ключевое слово this представляет собой контекст функции. Значение, на которое оно указывает, зависит от того, как была вызвана функция. Вот какие значения принимает ключевое слово this в зависимости от способа вызова функции (они, с примерами кода, конструкции из которых используются здесь, описаны выше):
- Обычный вызов функции — window / undefined .
- Вызов функции в виде метода объекта — theObject .
- Вызов функции в виде конструктора — новый объект.
- Вызов функции с использованием метода apply() — theObject .
- Вызов функции с использованием метода bind() — theObject .
▍Ключевое слово arguments
Ключевое слово arguments — это псевдопараметр, который даёт доступ ко всем аргументам, использованным при вызове функции. Он похож на массив, но массивом не является. В частности, у него нет методов массива.
Альтернативой ключевому слову arguments является новый синтаксис оставшихся параметров. В следующем примере args — это массив, содержащий всё, что передано функции при вызове.
▍Оператор return
Функция, в которой отсутствует выражение return , возвратит undefined . Используя ключевое слово return , обращайте внимание на то, как работает механизм автоматической вставки точки с запятой. Например, следующая функция вернёт не пустой объект, а значение undefined :
Для того чтобы избежать подобной проблемы, открывающую фигурную скобку нужно расположить на той же строке, на которой находится оператор return :
Динамическая типизация
JavaScript является языком с динамической типизацией. Это означает, что конкретные значения имеют типы, а переменные — нет. Во время выполнения программы в одну и ту же переменную можно записывать значения разных типов. Вот пример функции, которая работает со значениями разных типов:
Для выяснения типа данных, хранящихся в переменной, можно использовать оператор typeof() :
Однопоточная модель выполнения
Среда выполнения JavaScript является однопоточной. Это, в частности, выражается в невозможности одновременного выполнения двух функций (если не учитывать возможности асинхронного выполнения кода, которые мы тут не затрагиваем). В среде выполнения имеется так называемая очередь событий (Event Queue), хранящая список заданий, которые нужно обработать. Как результат, для однопоточной схемы выполнения JS несвойственна проблема взаимных блокировок ресурсов, поэтому тут не нужен механизм блокировок. Однако, код, попадающий в очередь событий, должен выполняться быстро. Если перегрузить тяжёлой работой, в браузерном приложении, главный поток, страница приложения не будет реагировать на воздействия пользователя и браузер предложит закрыть эту страницу.
Обработка исключений
В JavaScript имеется механизм для обработки исключений. Работает он по вполне обычному для подобных механизмов принципу: код, который может вызвать ошибку, оформляют с использованием конструкции try/catch . Сам код находится в блоке try , ошибки обрабатываются в блоке catch .
Интересно отметить, что иногда JavaScript, при возникновении внештатных ситуаций, не выдаёт сообщений об ошибках. Это связано с тем фактом, что JS не выбрасывал ошибки до принятия стандарта ECMAScript 3.
Например, в следующем фрагменте кода попытка изменения «замороженного» объекта завершится неудачно, но исключение выдано не будет.
Некоторые из «молчаливых» ошибок JS проявляются в строгом режиме, включить его можно, воспользовавшись конструкцией «use strict»; .
Система прототипов
В основе таких механизмов JS, как функции-конструкторы, команда Object.create() , ключевое слово class , лежит система прототипов.
Рассмотрим следующий пример:
Здесь, для создания объекта specializedService , прототипом которого нужно было сделать объект service , использована команда Object.create() . В результате оказывается, что метод doSomething() можно вызвать, обратившись к объекту specializedService . Кроме того, это означает, что свойство __proto__ объекта specializedService указывает на объект service .
Создадим теперь похожий объект с использованием ключевого слова class :
Методы, объявленные в классе Service , будут добавлены в объект Service.prototype . Экземпляры класса Service будут иметь тот же прототип ( Service.prototype ). Все экземпляры будут делегировать вызовы методов к объекту Service.prototype . В результате оказывается, что методы объявляются лишь один раз, в Service.prototype , после чего «наследуются» всеми экземплярами класса.
▍Цепочка прототипов
Объекты могут быть «наследниками» других объектов. У каждого объекта есть прототип, методы которого ему доступны. Если попытаться обратиться к свойству, которого нет в самом объекте, JavaScript приступит к его поиску в цепочке прототипов. Этот процесс будет продолжаться до тех пор, пока свойство не будет найдено, или пока поиск не достигнет конца цепочки.
О функциональном программировании в JavaScript
В JavaScript функции являются объектами первого класса, язык поддерживает механизм замыканий. Это открывает путь к реализации методик функционального программирования в JS. В частности, речь идёт о возможности применения функций высшего порядка.
Замыкание — это внутренняя функция, у которой есть доступ к переменным, объявленным внутри родительской функции, даже после выполнения родительской функции.
Функция высшего порядка — это функция, которая способна принимать другие функции в качестве аргументов, возвращать функции, или делать и то и другое.
Функциональное программирование в JS освещается во множестве публикаций. Если вам это интересно — вот несколько материалов на данную тему, посвящённых функциям первого класса, композиции, декораторам, замыканиям и удобочитаемости кода, написанного в функциональном стиле.
Итоги
Мощь JavaScript кроется в его простоте. Понимание базовых механизмов языка позволяет программисту, использующему JS, эффективнее применять эти механизмы и закладывает фундамент для его профессионального роста.
Уважаемые читатели! Как вы думаете, какие особенности JavaScript вызывают больше всего проблем у новичков?
Основы основ в JavaScript для того, чтобы идти дальше
![]()
Эта статья включает в себя все основные принципы работы в JavaScript, которые вам понадобятся для понимания библиотек, фреймворков, нового функционала, классовости со всей её разносторонностью и много всего другого связанного с этим языком программирования.
По-факту это адаптированный перевод четырёх статей, со сносками на другие, более детальные статьи по этим же темам из моего блога:
Мой Твиттер — там много из мира фронтенда, да и вообще поговорим. Подписывайтесь, будет интересно: ) ✈️
Оглавление статьи
Примитивы
Числа, булины(или логический тип данных, булины это сленг для простоты упоминания в и так сложных для восприятия текстах), строки, undefined и null это всё примитивы.
Числа
Есть только один тип числа в JavaScript, это число двойной точности. Арифметика десятичных чисел не является точной.
Как вы уже можете знать, 0.1 + 0.2 не выдаст в результате 0.3 . Но с целыми числами, такая арифметика будет верна, так что 1+2 === 3 .
Числа наследуют методы из объекта Number.prototype . Методы могут вызываться на числах:
Есть глобальные функции для конвертирования в числа: parseInt() , parseFloat() и Number() :
Неверные арифметические операции или неверные конверсии не будут обрабатываться как исключения, а выдадут NaN (Not-a-Number) значение. isNan() может определять NaN .
Оператор + может добавлять или конкатенировать:
Строки
Строки хранят в себе набор символов Unicode. Текст может находиться внутри двойных скобок “” или одинарных ‘’.
У строк есть такие замечательные методы, как: substring() , indexOf() и конечно же concat() .
Строки ведут себя как примитивы, они постоянны. Для примера, concat() не модифицирует существующую строку, но создаёт новую.
Булины
У булинов есть только два значения: true и false .
То есть простым языком, верное и ложное значение. false , null , undefined , ‘’ , 0 и NaN выдают false . Все другие значения, включая все объекты, выдают true.
Верное значение это true, говоря в контексте булинов. Ложное это false , соответственно. Посмотрите на следующий пример, показывающий результат при false .
Переменные
Назначать переменные можно используя var , let и const .
var объявляет и при необходимости инициализирует переменную. Значение переменной, которая не инициализирована — undefined . Переменные объявляются с помощью var имеют функциональную область видимости.
Переменные let , имеют блочную область видимости.
Переменные объявленные с помощью const не могут быть переназначены. Но их значение, вопреки, все таки может быть изменено. const замораживает переменную, Object.freeze() замораживает объект. cosnt имеет блочную область видимости.
Область видимости переменной, объявленной вне любой функции является глобальной. Более подробно об этом можно почитать в этой статье — Разбираемся с “поднятием” (hoisting) в JavaScript
Функции
Функции это независимые единицы поведения. Функции это объекты. Функции могут быть назначены переменным, храниться в массивах или объектах, передаваться как аргумент для другой функции и возвращаться из других функций.
Есть три способа определения функции:
Объявление функции
Функциональное выражение
Стрелочная функция
Объявление функции
Function это первое слово в строке, оно должно иметь имя, оно может использоваться для определения. Объявленные функции “поднимаются” вверх своей области видимости.
Функциональное выражение
Function не является первым словом в строке. Имя ей вообще опционально. Тут может быть анонимное функциональное выражение или названное.
Оно должно быть сначала определено, а уже затем оно может выполниться.
Оно может автоматически выполняться после объявления (Это называется IIFE, то есть немедленно вызываемые функции)
Стрелочная функция
Это очень удобный синтаксис для создания анонимных функциональных выражений.
У стрелочных функций нет собственного this и аргументов.
Вызов функции
Функция определенная с помощью function , может быть вызвана разными способами:
Функции могут быть вызваны с большим или меньшим количеством аргументов, чем указано в определении. Дополнительные аргументы будут проигнорированы, а недостающие параметры получат undefind .
this представляет контекст функции. Только функции объявленные с помощью function, имеют свой собственный this контекст. Его значение зависит от того, как была вызвана функция. Давайте посмотрим значения this, зависящие от формы вызова doSomething() :
arguments
Псевдопараметр arguments дается всем аргументам применяемым в вызове. Это схожий объект, проходящий на массив, но на самом деле не массив. Ему не хватает методов массива.
Альтернативой является новый синтаксис параметров. В этот раз args это множественный объект.
Функция без return отдаст undefined . Обращайте внимание на вставление точки с запятой при использовании return. Следующая функция не отдаст пустой объект, а выдаст undefined .
Чтобы избежать этой проблемы, используйте < на одной строке с return >:
Массивы
Есть два синтаксиса для создания пустого массива:
Выше у нас есть как и объявленные, так и назначенные значения в одном объявлении.
Добавляем данные с использованием push
Это синтаксис добавления данных в массив, он довольно прост — arrayname.push(item) .
Когда мы добавляем данные с использованием push , то они добавляются в конец массива.
Добавление данных с использованием unshift
А это синтаксис для подставки данных в массив — arrayname.unshift(item) .
Когда мы добавляем данные с использованием unshift , то они добавляются в начало, так как в unshift все элементы массива сдвигаются на одну позицию вправо и первое место остаётся за добавляемым значением.
В примере выше несколько элементов добавлены в массив с использованием push и unshift , синтаксисами arrayname.push(item1,item2,item3..) и arrayname.unshift(item1,item2,item3….) .
Удаление элементов с использованием pop
Это синтаксис для вырывания элемента из массива — arrayname.pop() .
Когда мы удаляем элемент с использованием pop, элемент удаляется с конца.
Удаляем элемент с использованием shift
Добавление, обновление, удаление элементов с использованием splice
Тут индекс обозначает позицию, удаляет число элементов указанных в deleteCount и затем вставляет элементы представленные с elem1 до elemN .
Пример 1. Удаление.
Так вот, выше удалиться один элемент, начиная с индекса 1.
Пример 2. Удаление и вставление
Тут начиная с индекса 0 до 3, элементы будут удалены, а 2 элемента будут добавлены. Таким образом, конечный массив будет выглядеть именно так, как в примере кода выше. Если мы попытаемся вернуть splice, то он вернет массив удаленных элементов.
Пример 3. Вставление
Тут удаляется 0 элементов и со второго индекса добавляются два элемента.
Создаем подмассивы, используя slice
Тут start определяет позицию с которой вы хотите начать и end определяет индекс того, где вы хотите закончить. Так что в соответствии со Start и end указанными индексами, функция slice вернёт копию массива от start до end , но не включая end .
Объединяем массивы с элементами или массивами, используя concat
Concat возвращает новый массив, соединяя массивы с аргументами, которые могут быть как элементами, так и массивами.
Поиск
Тут методы схожи с теми, которые используются для строк, но работают на элементах, вместо символов.
arr.indexOf(item, from) ищет элемент item , начиная с элемента from и возвращает индекс найденного элемента, в проливном случае возвращается -1 .
arr.lastIndexOf(item, from) — тоже самое, только ищет с права налево.
arr.includes(item, from) — ищет элемент item , начиная с индекса from, возвращая true при нахождении его.
Эти методы используют === для сравнения.
Если нам просто нужно знать, содержит ли массив нужный элемент, то тогда мы используем includes. Также includes может правильно обрабатывать NaN , в отличии от indexOf и lastIndexOf .
Найти и найти индекс
Синтаксис сверху возвращает элемент, если находит его или если ничего не находится, то возвращается undefined .
И так, выше мы использовали стрелочную функцию, где элемент это аргумент и мы отдаем элемент, где item.id == 1 .
findIndex делает тоже самое, только отдаёт индекс найденного элемента, вместо самого элемента.
Filter
Функция фильтра работает также, как и find , но вместо отдачи просто первого элемента, она возвращает все подходящие элементы.
Пример ниже отдаёт все элементы, где item.id < 3 .
Трансформируем массив
Ниже находятся функции, которые трансформируют или меняют порядок массива, без изменения чего-либо в оригинальном массиве. Это рассматривается, как один из самых важных подходов, так что уделите время для того, чтобы понять этот.
Map
Тут результат переменной отдаёт то что сделала функция с массивом, без изменения самого массива. Для примера, ниже у нас есть новый массив, где каждый элемент конвертируется в свою длину.
И тут мы снова применяем стрелочную функцию, где элемент это аргумент и каждый элемент трансформируется в свою длину.
Reduce
Для итерирования по массиву мы можем использовать loop . Для трансформирования значения каждого элемента, мы можем использовать maps. Но если мы хотим отдать одно значение, основанное на всём массиве, то нам на помощь приходит reduce.
Тут previousValue означает значение, которое оно возвращает с предидущего вызова. Индекс указывает откуда нам начать применять функцию, а initial в конце, определяет изначальное значение previousValue. Давайте посмотрим на пример, чтобы понять это получше.
В это функции sum это previousValue и назначено изначальное значение равное нулю. Функция возвращает sum + current в каждом запросе и так как индекс не указан, он покрывает весь массив. И в конце он возвращает сумму всех элементов массива.
Иной принцип объяснения некоторых методов можно прочитать в этих статьях моего блога.
Объекты
Вот синтаксис для создания новых объектов.
Тут мы добавляем новое булинное свойство.
Тут мы удаляем свойство из объекта.
Тут давайте посмотрим, как мы назначаем значения свойств объектам, используя функции.
А вот сокращение для этого же. Так как мы назначаем имя свойства имени аргумента, то мы можем избежать дополнительный синтаксис, выполнив этот.
Давайте посмотрим, как мы можем получить значения ключей объекта, используя цикл.
Рассмотрим, как это выполняется в реальной жизни.
Методы объекта
Если бы у нас был объект как ниже, то мы смогли бы посмотреть на то, как мы можем применять методы объектов для доступа к ключам, значениям и к тому и другому.
Деструктуризация
Деструктуризационное назначение это специальный синтаксис, который позволяет “распаковать” массив или объект в кучку переменных, так как зачастую это гораздо удобнее. Деструктуризация также часто отлично работает с сложными функциями, которые имеют множество параметров, стандартных значений и т.п. Сейчас вы увидите как это прекрасно работает и как с этим справляет деструктуризация.
Начнем с объектов:
Теперь посмотрим на массивы:
Посмотрите ещё на парочку интересных моментов в деструктуризации:
В примере выше, мы назначаем свойства объекта деструктуризацией.
Пример выше хорош тогда, когда мы можем получить связку ключ-значение из объекта, используя деструктуризацию в цикле.
Вообще деструктуризация это очень сложная, но полезная тема. Примеры выше дают только понятие того, что это такое. В этой статье Деструктуризация в ES6. Полное руководство можно подробно узнать о том, как работает реструктуризация в JavaScript. Обязательно углубитесь в эту тему, она сможет сэкономить вам уйму времени и сил.
Классы
Это очень важный момент для понимания библиотек, современных фреймворков и т.п. Очень внимательно прочтите этот раздел.
Классы это функции
Класс в JavaScript это тип функции. Классы объявляются с помощью слова class. Сейчас мы будем использовать функциональное выражение для инициализации функции и классовое выражение для инициализации класса.
Мы можем получить доступ к [[Prototype]] объекта, используя метод Object.getPrototypeOf() . Давайте его используем, чтобы протестировать созданную нами, пустую функцию.
Код созданный с помощью function и class , возвращает функцию [[Prototype]] . С прототипами, любая функция функция может быть стать экземпляром конструктора при использовании слова new.
Это также применимо и к классам:
Эти примеры конструкторов пусты, но мы можем видеть как в глубине синтаксиса, оба метода достигают одного и того же результата.
Создаем класс
Функция конструктор инициализируется с параметрами, которые будут назначены как свойства от this в отношении самой функции. Первая буква в названии должна писаться с большой буквы.
Когда мы переводим её в классовый синтаксис, показанный ниже, то мы видим, что он структурирован очень похоже.
Мы знаем, что функция конструктор подразумевается как план объекта, при написании первой буквы инициализатора с заглавной и с помощью схожести синтаксиса. Слово class более понятное и доходчивое, учитывая цели нашей функции.
Единственная разница в инициализации это использование слова class, вместо function и назначение свойств внутри метода constructor().
Создание методов
Распространенная практика с функцией конструтором в том, чтобы назначать методы напрямую prototype, вместо инициализации, это видно на примере метода greet() ниже:
При помощи классов этот синтаксис упрощается и метод может быть добавлен напрямую в класс. Используя сокращенное создание классов из ES6, теперь этот процесс гораздо короче.
Давайте посмотрим на свойства и методы в действии. Мы создадим новый экземпляр Hero , с использованием слова new и назначим ему несколько значений.
Если мы выведем больше информации о нашем новом объекте с помощью console.log(hero1) , то мы можем увидеть больше деталей о том, что происходит с классом при инициализации.
Мы можем видеть в выводе, что constructor() и greet() функции, были применены к _proto_ или [[Prototype]] от hero1 и не напрямую как метод на объекте hero1 . Когда это понятно создание функций конструктора, это не так очевидно при создании классов.
В случае с классами мы получаем более простой и сжатый синтаксис, но жертвуем некоей ясностью в процессе.
Наследование
Преимущество функции конструктора и классов в том, что они могут наследоваться в новый объект, основанный на родителе. Это исключает повторения в коде для похожих объектов, но требует дополнительных и более специфичных функций.
Новые функции конструктора могут быть созданы из родителя с использованием метода call() . В примере ниже мы создадим специальный класс персонажа под именем Mage и назначим свойства для Hero, используя call() , также как и добавив дополнительные свойства.
На этом этапе мы можем создать новый экземпляр Mage , используя одни и те же свойства, что и Hero , так и новые добавленные.
Отправляя hero2 в консоль, мы можем видеть, что новый Mage основан на конструкторе.
С классами ES6, слово super использует вместо call , чтобы получить доступ к родительским функциям. Мы будем использовать extends , чтобы сослаться к родительскому классу.
И так, теперь мы можем создать новый экземпляр Mage , тем же способом.
Вывод практически тот же самый, кроме того, что класс конструктора [[Prototype]] , ссылается на родителя, а в этом случае это Hero .
Ниже вы увидите прямо сравнение всего процесса инициализации, добавления методов и наследования функции конструктора и класса.
Хоть синтаксис и довольно отличается, лежащий в основе результат среди двух методов почти такой же. Классы дают нам более сжатый способ создания макетов для объектов, а конструктор функция более точно описывает то, что происходит внутри “под капотом”.
Динамическое типизирование
У JavaScript есть динамическое типизирование. У значений есть типы, у переменных нет. Типы могут меняться в процессе работы.
Однопоточность
Основы рабочего процесса в JavaScript однопоточны. Две функции не могут быть запущены одновременно. Рабочий процесс содержит очередь событий, которые хранят список того, что нужно выполнить. Тут нет состояний гонки или тупиков с взаимными блокировками. Однако, коду в очереди событий нужно работать быстрее. В противном случае, браузер перестанет отвечать и запросит завершение задачи.
Исключения
У JavaScript есть механизм обработки исключений. Он работает так, как вы и подумали, обертывая код с использованием try/catch . Есть только один блок catch, который кэширует все исключения.
Очень полезно знать то, что JavaScript иногда имеет предпочтения для скрытых ошибок. Следующий код не выкинет исключение при попытке изменения замороженного объекта:
Strict mode устраняет некоторые скрытые ошибки в JavaScript. Что бы его включить, используйте “use strict” ;
Паттерны прототипов
Object.create() , функция конструктор и class , создают объекты по системе прототипов. Рассмотрим следующий пример:
Я использовал Object.create() , чтобы создать новый объект specializedService , который имеет объект service, в виде прототипа. Это означает то, что doSomething() доступно на объекте specializedService . Также это означает то, что свойство _proto_ объекта specializedService указывает на объект service.
Давайте сделаем схожий объект, используя class .
Все методы определенные в классе Service , будут добавлены объекту Service.prototype. Экземпляры класса Service будут иметь тот же объект прототип ( Service.prototype ). Все они будут отсылать запросы методов к Service.prototype объекту. Методы определяются единожды в Service.prototype и потом наследуются всеми экземплярами.
Цепочки прототипов
Объекты наследуют от других объектов. У каждого объекта есть прототип и он наследует свои свойства из него. Прототип может выдать скрытое свойство _proto_ .
Когда вы запрашиваете свойство, которое не содержит объект, JavaScript посмотрит вниз по цепочке прототипов до тех пор пока он либо не найдет запрашиваемое свойство, либо не дойдет до конца цепочки.
Model-view-controller это дизайн фреймворк (не язык программирования), который позволяет нам разделять поведение в практическую, реальную структуру. Практически 85% веб-приложений на данный момент содержат в основе этот паттерн, в том или ином виде. Есть другие типы дизайн фреймворков, но этот пока что самый фундаментальный и легкий для понимания паттерн.
Выражения и операторы
Эта глава описывает выражения и операторы языка JavaScript, такие как операторы присваивания, сравнения, арифметические, битовые, логические, строчные, и различные специальные операторы.
Полный и детальный список операторов и выражений также доступен в этом руководстве.
Операторы
В JavaScript есть следующие типы операторов. Данный подраздел описывает каждый тип и содержит информацию об их приоритетах друг над другом.
JavaScript поддерживает бинарные и унарные операторы, а также ещё один специальный тернарный оператор — условный оператор. Бинарная операция использует два операнда, один перед оператором и другой за ним:
Например: 3+4 или x*y .
В свою очередь унарная операция использует один операнд, перед или после оператора:
Например: x++ или ++x .
Операторы присваивания
В результате операции присваивания операнду слева от оператора присваивания (en-US) (знак » table-container»>
| Имя | Сокращённый оператор | Смысл |
|---|---|---|
| Присваивание (en-US) | x = y | x = y |
| Присваивание со сложением (en-US) | x += y | x = x + y |
| Присваивание с вычитанием (en-US) | x -= y | x = x — y |
| Присваивание с умножением (en-US) | x *= y | x = x * y |
| Присваивание с делением (en-US) | x /= y | x = x / y |
| Присваивание по модулю (en-US) | x %= y | x = x % y |
| Присваивание с левым сдвигом (en-US) | x <<= y | x = x << y |
| Присваивание с правым сдвигом (en-US) | x >>= y | x = x >> y |
| Присваивание с беззнаковым сдвигом вправо (en-US) | x >>>= y | x = x >>> y |
| Присваивание с побитовым AND (en-US) | x &= y | x = x & y |
| Присваивание с побитовым XOR (en-US) | x ^= y | x = x ^ y |
| Присваивание с побитовым OR (en-US) | x |= y | x = x | y |
Деструктуризация
Для более сложного присваивания в JavaScript есть синтаксис деструктуризации — это выражение, которое позволяет извлекать данные из массивов или объектов, используя синтаксис, который зеркалирует конструкторы массивов и литералы объектов.
Операторы сравнения
Оператор сравнения (en-US) сравнивает свои операнды и возвращает логическое значение, базируясь на истинности сравнения. Операнды могут быть числами, строками, логическими величинами или объектами. Строки сравниваются на основании стандартного лексикографического порядка, используя Unicode-значения. В большинстве случаев, если операнды имеют разный тип, то JavaScript пробует преобразовать их в тип, подходящий для сравнения. Такое поведение обычно происходит при сравнении числовых операндов. Единственным исключением из данного правила является сравнение с использованием операторов === и !== , которые производят строгое сравнение на равенство или неравенство. Эти операторы не пытаются преобразовать операнды перед их сравнением. Следующая таблица описывает операторы сравнения в контексте следующего примера кода:
| Оператор | Описание | Примеры, возвращающие true |
|---|---|---|
| Равно ( == ) | Возвращает true, если операнды равны. | 3 == var1 «3» == var1 3 == ‘3’ |
| Не равно ( != ) | Возвращает true, если операнды не равны. | var1 != 4 var2 != «3» |
| Строго равно ( === ) | Возвращает true, если операнды равны и имеют одинаковый тип. Смотрите также Object.is и sameness in JS. | 3 === var1 |
| Строго не равно( !== ) | Возвращает true, если операнды не равны и/или имеют разный тип. | var1 !== «3» 3 !== ‘3’ |
| Больше ( > ) | Возвращает true, если операнд слева больше операнда справа. | var2 > var1 «12» > 2 |
| Больше или равно ( >= ) | Возвращает true, если операнд слева больше или равен операнду справа. | var2 >= var1 var1 >= 3 |
| Меньше ( < ) | Возвращает true, если операнд слева меньше операнда справа. | var1 < var2 «2» < 12 |
| Меньше или равно ( <= ) | Возвращает true, если операнд слева меньше или равен операнду справа. | var1 <= var2 var2 <= 5 |
Примечание: (=>) не оператор, а нотация Стрелочных функций.
Арифметические операторы
Арифметические операторы (en-US) используют в качестве своих операндов числа (также литералы или переменные) и в качестве результата возвращают одно числовое значение. Стандартными арифметическими операторами являются сложение (+), вычитание (-), умножение (*), и деление (/). При работе с числами с плавающей точкой эти операторы работают аналогично их работе в большинстве других языках программирования (обратите внимание, что деление на ноль возвращает бесконечность Infinity ). Например:
Кроме того, JavaScript позволяет использовать следующие арифметические операторы, представленные в таблице:
| Оператор | Описание | Пример |
|---|---|---|
| Остаток от деления (en-US) ( % ) | Бинарный оператор. Возвращает целочисленный остаток от деления двух операндов. | 12 % 5 вернёт 2. |
| Инкремент (en-US) ( ++ ) | Унарный оператор. Добавляет единицу к своему операнду. Если используется в качестве префикса ( ++x ), то возвращает значение операнда с добавленной к нему единицей; а в случае применения в качестве окончания ( x++ ) возвращает значение операнда перед добавлением к нему единицы. | Если x равно 3, тогда ++x установит значение x равным 4 и вернёт 4, напротив x++ вернёт 3 и потом установит значение x равным 4. |
| Декремент (en-US) ( — ) | Унарный оператор. Вычитает единицу из значения своего операнда. Логика данного оператора аналогична оператору инкремента. | Если x равно 3, тогда —x установит значение x равным 2 и вернёт 2, напротив x— вернёт 3 и потом установит значение x равным 2. |
| Унарный минус (en-US) — | Унарный оператор. Возвращает отрицательное значение своего операнда. | Если x равно 3, тогда -x вернёт -3. |
| Унарный плюс (en-US) ( + ) | Унарный оператор. Пытается конвертировать операнд в число, если он ещё не оно. | +»3″ вернёт 3 . +true вернёт 1. |
| Возведение в степень (en-US) ( ** ) Экспериментальная возможность | Возводит основание в показатель степени , как, основаниестепень | 2 ** 3 вернёт 8 . 10 ** -1 вернёт 0.1 . |
Битовые (поразрядные) операторы
Битовые операторы (en-US) обрабатывают свои операнды как последовательности из 32 бит (нулей и единиц), а не как десятичные, шестнадцатеричные или восьмеричные числа. Например, десятичное число 9 имеет двоичное представление 1001. Битовые операторы выполняют операции над таким двоичным представлением, но результат возвращают как обычное числовое значение JavaScript.
Следующая таблица обобщает битовые операторы JavaScript.
Битовые логические операторы
Основной смысл работы битовых логических операторов состоит в следующем:
-
Операнды преобразуются в 32-битные целые числа и представляются в виде последовательности бит (нулей и единиц). Числа, имеющие более 32 битов будут сокращены. Например, следующее число имеет больше 32 битов и сконвертируется в 32-х битное:
Например, двоичным представлением числа 9 является 1001, а двоичным представлением пятнадцати — 1111. Результаты применения к этим числам битовых логических операторов выглядят следующим образом:
Обратите внимание, что все 32 бита преобразуются с использованием битового оператора НЕ, и что величины с наиболее значимым (самым левым) битом равным 1 представляют собой отрицательные числа (в представлении дополнения до двух).
Битовые операторы сдвига
Битовые операторы сдвига используют два операнда: первый представляет величину, подлежащую сдвигу, а второй операнд указывает число битовых позиций на которое должен быть сдвинут первый операнд. Направление операции сдвига определяется используемым оператором.
Операторы сдвига преобразуют свои операнды в 32-битные целые числа и возвращают результат того же типа, каким является левый операнд.
Операторы сдвига перечислены в следующей таблице.
| Оператор | Описание | Пример |
|---|---|---|
| [Сдвиг влево](</ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#<<_(Left_shift)>) ( << ) | Данный оператор сдвигает первый операнд на указанное количество бит влево. Излишние биты, сдвинутые влево, отбрасываются. Справа число дополняется нулевыми битами. | 9<<2 равно 36, так как 1001 после сдвига на 2 бита влево превращается в 100100, что соответствует числу 36. |
| [Сдвиг вправо с переносом знака](</ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#>>_(Sign-propagating_right_shift)>) ( >> ) | Данный оператор сдвигает первый операнд на указанное количество бит вправо. Излишние биты, сдвинутые вправо, отбрасываются. Слева число дополняется копиями крайнего слева бита. | 9>>2 равно 2, так как 1001 после сдвига на 2 бита вправо превращается в 10, что соответствует числу 2. Подобным же образом -9>>2 равно -3, так как знак сохраняется. |
| [Сдвиг вправо с заполнением нулями](</ru/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#>>>_(Zero-fill_right_shift)>) ( >>> ) | Данный оператор сдвигает первый операнд на указанное количество бит вправо. Излишние биты, сдвинутые вправо, отбрасываются. Слева число дополняется нулевыми битами. | 19>>>2 равно 4, так как 10011 после сдвига на 2 бита вправо превращается в 100, что соответствует числу 4. Для неотрицательных чисел сдвиг вправо с заполнением нулями и сдвиг вправо с переносом знака дают одинаковый результат. |
Логические операторы
Логические операторы (en-US) обычно используются с булевыми (логическими) значениями; при этом возвращаемое ими значение также является булевым. Однако операторы && и || фактически возвращают значение одного из операндов, поэтому, если эти операторы используются с небулевыми величинами, то возвращаемая ими величина также может быть не булевой. Логические операторы описаны в следующей таблице.
| Оператор | Использование | Описание |
|---|---|---|
| Логическое И (en-US) «( && ) | expr1 && expr2 | (Логическое И) Возвращает операнд expr1 , если он может быть преобразован в false ; в противном случае возвращает операнд expr2 . Таким образом, при использовании булевых величин в качестве операндов, оператор && возвращает true , если оба операнда true ; в противном случае возвращает false . |
| Логическое ИЛИ (en-US) ( || ) | expr1 || expr2 | (Логическое ИЛИ) Возвращает операнд expr1 , если он может быть преобразован в true ; в противном случае возвращает операнд expr2 . Таким образом, при использовании булевых величин в качестве операндов, оператор || возвращает true , если один из операндов true ; если же оба false , то возвращает false . |
| Логическое НЕ (en-US) ( ! ) | !expr | (Логическое НЕ) Возвращает false , если операнд может быть преобразован в true ; в противном случае возвращает true . |
Примерами выражений, которые могут быть преобразованы в false являются: null, 0, NaN, пустая строка («») или undefined.
Следующий код демонстрирует примеры использования оператора && (логическое И).
Следующий код демонстрирует примеры использования оператора || (логическое ИЛИ).
Следующий код демонстрирует примеры использования оператора ! (логическое НЕ).
Сокращённая оценка
Так как логические выражения вычисляются слева направо, они проверяются на возможность выполнения сокращённой оценки с использованием следующих правил:
- false && anything — сокращение с результатом false.
- true || anything — сокращение с результатом true.
Правила логики гарантируют, что данные вычисления всегда корректны. Обратите внимание, что часть «anything» представленных выше выражений не вычисляется, таким образом удаётся избежать любых побочных эффектов вычисления данной части.
Строковые операторы
В дополнение к операторам сравнения, которые могут использоваться со строковыми значениями, оператор (+) позволяет объединить две строки, возвращая при этом третью строку, которая представляет собой объединение двух строк-операндов:
Сокращённый оператор присваивания += также может быть использован для объединения (конкатенации) строк:
Условный (тернарный) оператор
Условный оператор является единственным оператором JavaScript, который использует три операнда. Оператор принимает одно из двух значений в зависимости от заданного условия. Синтаксис оператора:
Предупреждение: val1 и val2 обязательно должны что-то возвращать, поэтому в этой конструкции нельзя использовать continue или break
Если condition (условие) — истина, то оператор принимает значение val1 . В противном случае оператор принимает значение val2 . Вы можете использовать условный оператор во всех случаях, где может быть использован стандартный оператор.
Данное выражение присваивает значение «adult» переменной status , если age имеет значение 18 или более. В противном случае переменной status присваивается значение «minor».
Оператор запятая
Оператор запятая ( , ) просто вычисляет оба операнда и возвращает значение последнего операнда. Данный оператор в основном используется внутри цикла for , что позволяет при каждом прохождении цикла одновременно обновлять значения нескольких переменных.
Например, если a является двумерным массивом, каждая строка которого содержит 10 элементов, то следующий код с использованием оператора запятая позволяет выполнять одновременное приращение двух переменных. Данный код выводит на экран значения диагональных элементов массива:
Унарные операторы
Унарная операция — операция только с одним операндом.
delete
Оператор delete выполняет удаление объекта, свойства объекта, или элемента массива с заданным индексом. Синтаксис оператора:
где objectName представляет собой имя объекта, property — свойство объекта, а index — целое число, указывающее на положение (номер позиции) элемента в массиве.
Четвёртый вариант использования позволяет удалить свойство объекта, но допускается только внутри with .
Вы можете использовать оператор delete для удаления переменных, объявленных неявно, но вы не можете с его помощью удалять переменные, объявленные с помощью var .
После применения оператора delete свойство элемента меняется на undefined . Оператор delete возвращает true если выполнение операции возможно; оператор возвращает false , если выполнение операции невозможно.
Удаление элементов массива
Удаление элемента массива не влияет на длину массива. Например, если вы удалите a[3] , элемент a[4] останется a[4], a[3] станет undefined.
Когда элемент массива удаляется с помощью оператора delete , то из массива удаляется значение данного элемента. В следующем примере элемент trees[3] удалён с помощью оператора delete . Однако, элемент trees[3] остаётся адресуемым и возвращает значение undefined .
Если вы хотите, чтобы элемент оставался в массиве, но имел значение undefined, то используйте ключевое слово undefined вместо оператора delete . В следующем примере элементу trees[3] присвоено значение undefined , но элемент при этом остаётся в массиве:
Оператор typeof
Оператор typeof используется одним из следующих способов:
Оператор typeof возвращает строку обозначающую тип невычисленного операнда. Значение operand может быть строкой, переменной, дескриптором, или объектом, тип которого следует определить. Скобки вокруг операнда необязательны.
Предположим, вы определяете следующие переменные:
Оператор typeof возвращает следующие результаты для этих переменных:
Для дескрипторов true и null оператор typeof возвращает следующие результаты:
Для чисел и строк оператор typeof возвращает следующие результаты:
Для свойств оператор typeof возвращает тип значения данного свойства:
Для методов и функций оператор typeof возвращает следующие результаты:
Для встроенных объектов оператор typeof возвращает следующие результаты:
Оператор void
Оператор void используется любым из следующих способов:
Оператор void определяет выражение, которое должно быть вычислено без возвращения результата. expression — это выражение JavaScript, требующее вычисления. Скобки вокруг выражения необязательны, но их использование является правилом хорошего тона.
Вы можете использовать оператор void для указания на то, что операнд-выражение является гипертекстовой ссылкой. При этом выражение обрабатывается, но не загружается в текущий документ.
Следующий код служит примером создания гипертекстовой ссылки, которая бездействует при нажатии на неё пользователем. Когда пользователь нажимает на ссылку, void(0) вычисляется равным undefined , что не приводит ни к каким действиям в JavaScript.
Приведённый ниже код создаёт гипертекстовую ссылку, которая подтверждает отправку формы при клике на ней пользователем:
Операторы отношения
Оператор отношения сравнивает свои операнды и возвращает результат сравнения в виде булева значения.
Оператор in
Оператор in возвращает true, если указанный объект имеет указанное свойство. Синтаксис оператора:
где propNameOrNumber — строка или числовое выражение, представляющее имя свойства или индекс массива, а objectName — имя объекта.
Некоторые примеры способов использования оператора in :
Оператор instanceof
Оператор instanceof возвращает true, если заданный объект является объектом указанного типа. Его синтаксис:
где objectName — имя объекта, тип которого необходимо сравнить с objectType , а objectType — тип объекта, например, Date или Array .
Используйте оператор instanceof , когда вам необходимо подтвердить тип объекта во время выполнения программы. Например, при перехвате исключений вы можете создать различные программные переходы для обработки исключений в зависимости от типа обрабатываемого исключения.
Например, следующий код использует оператор instanceof для проверки того, является ли объект theDay объектом типа Date . Так как theDay действительно является объектом типа Date , то программа выполняет код, содержащийся в утверждении if .
Приоритет операторов
Приоритет операторов определяет порядок их выполнения при вычислении выражения. Вы можете влиять на приоритет операторов с помощью скобок.
Приведённая ниже таблица описывает приоритет операторов от наивысшего до низшего.
Более подробная версия данной таблицы, содержащая ссылки и дополнительную информацию по каждому оператору, находится в справочнике JavaScript.
Выражения
Выражением является любой корректный блок кода, который возвращает значение.
Концептуально, существуют два типа выражений: те которые присваивают переменной значение, и те, которые вычисляют значение без его присваивания.
Выражение x = 7 является примером выражения первого типа. Данное выражение использует оператор = для присваивания переменной x значения 7. Само выражение также равняется 7.
Код 3 + 4 является примером выражения второго типа. Данное выражение использует оператор «+» для сложения чисел 3 и 4 без присваивания переменной полученного результата 7.
Все выражения в JavaScript делятся на следующие категории:
- Арифметические: вычисляются в число, например: 3.14159 (Используют арифметические операторы).
- Строковые: вычисляются в текстовую строку, например: «Fred» или «234» (Используют строковые операторы).
- Логические: вычисляются в true или false (Используют логические операторы).
- Основные выражения: Базовые ключевые слова и основные выражения в JavaScript.
- Левосторонние выражения: Значениям слева назначаются значения справа.
Основные выражения
Базовые ключевые слова и основные выражения в JavaScript.
Оператор this
Используйте ключевое слово this для указания на текущий объект. В общем случае this указывает на вызываемый объект, которому принадлежит данный метод. Используйте this следующим образом:
Предположим, функция validate выполняет проверку свойства value некоторого объекта; задан объект, а также верхняя и нижняя граница величины данного свойства:
Вы можете вызвать функцию validate для обработчика события onChange для каждого элемента формы, используя this для указания на элемент формы, как это показано в следующем примере:
Оператор группировки
Оператор группировки «скобки» ( ) контролирует приоритет вычислений в выражениях. Например, вы можете переопределить порядок так, чтобы сложение выполнялось до умножения:
Упрощённый синтаксис создания массивов и генераторов
Упрощённый синтаксис — экспериментальная возможность JavaScript, которая возможно будет добавлена в будущие версии ECMAScript. Есть 2 версии синтаксиса:
Упрощённый синтаксис для массивов.
Упрощённый синтаксис для генераторов.
Упрощённые синтаксисы существуют во многих языках программирования и позволяют вам быстро собирать новый массив, основанный на существующем. Например:
Левосторонние выражения
Значениям слева назначаются значения справа.
Вы можете использовать оператор new для создания экземпляра объекта пользовательского типа или одного из встроенных объектов. Используйте оператор new следующим образом:
super
Ключевое слово используется, чтобы вызывать функции родительского объекта. Это полезно и с классами для вызова конструктора родителя, например.
Оператор расширения
Оператор расширения позволяет выражению расширяться в местах с множеством аргументов (для вызовов функций) или множестве элементов (для массивов).
Пример: Сегодня, если у вас есть массив и вы хотите создать новый с существующей частью первого, то литерального синтаксиса массива уже не достаточно, и вы должны писать императивный (без вариантов) код, используя комбинацию push , splice , concat и т.д. Но с этим оператором код становится более коротким: