знаки в ява скрипт
Тип данных Symbol
По спецификации, в качестве ключей для свойств объекта могут использоваться только строки или символы. Ни числа, ни логические значения не подходят, разрешены только эти два типа данных.
До сих пор мы видели только строки. Теперь давайте разберём символы, увидим, что хорошего они нам дают.
Символы
«Символ» представляет собой уникальный идентификатор.
Создаются новые символы с помощью функции Symbol() :
При создании символу можно дать описание (также называемое имя), в основном использующееся для отладки кода:
Символы гарантированно уникальны. Даже если мы создадим множество символов с одинаковым описанием, это всё равно будут разные символы. Описание – это просто метка, которая ни на что не влияет.
Например, вот два символа с одинаковым описанием – но они не равны:
Если вы знаете Ruby или какой-то другой язык программирования, в котором есть своего рода «символы» – пожалуйста, будьте внимательны. Символы в JavaScript имеют свои особенности, и не стоит думать о них, как о символах в Ruby или в других языках.
Большинство типов данных в JavaScript могут быть неявно преобразованы в строку. Например, функция alert принимает практически любое значение, автоматически преобразовывает его в строку, а затем выводит это значение, не сообщая об ошибке. Символы же особенные и не преобразуются автоматически.
К примеру, alert ниже выдаст ошибку:
Это – языковая «защита» от путаницы, ведь строки и символы – принципиально разные типы данных и не должны неконтролируемо преобразовываться друг в друга.
«Скрытые» свойства
Символы позволяют создавать «скрытые» свойства объектов, к которым нельзя нечаянно обратиться и перезаписать их из других частей программы.
Используем для этого символьный ключ:
Так как объект user принадлежит стороннему коду, и этот код также работает с ним, то нам не следует добавлять к нему какие-либо поля. Это небезопасно. Но к символу сложно нечаянно обратиться, сторонний код вряд ли его вообще увидит, и, скорее всего, добавление поля к объекту не вызовет никаких проблем.
Сторонний код может создать для этого свой символ Symbol(«id») :
Конфликта между их и нашим идентификатором не будет, так как символы всегда уникальны, даже если их имена совпадают.
А вот если бы мы использовали строку «id» вместо символа, то тогда был бы конфликт:
Символы в литеральном объекте
Если мы хотим использовать символ при литеральном объявлении объекта <. >, его необходимо заключить в квадратные скобки.
Это вызвано тем, что нам нужно использовать значение переменной id в качестве ключа, а не строку «id».
Символы игнорируются циклом for…in
Это – часть общего принципа «сокрытия символьных свойств». Если другая библиотека или скрипт будут работать с нашим объектом, то при переборе они не получат ненароком наше символьное свойство. Object.keys(user) также игнорирует символы.
Здесь нет никакого парадокса или противоречия. Так и задумано. Идея заключается в том, что, когда мы клонируем или объединяем объекты, мы обычно хотим скопировать все свойства (включая такие свойства с ключами-символами, как, например, id в примере выше).
Глобальные символы
Для этого существует глобальный реестр символов. Мы можем создавать в нём символы и обращаться к ним позже, и при каждом обращении нам гарантированно будет возвращаться один и тот же символ.
Символы, содержащиеся в реестре, называются глобальными символами. Если вам нужен символ, доступный везде в коде – используйте глобальные символы.
В некоторых языках программирования, например, Ruby, на одно имя (описание) приходится один символ, и не могут существовать разные символы с одинаковым именем.
В JavaScript, как мы видим, это утверждение верно только для глобальных символов.
Symbol.keyFor
Системные символы
Существует множество «системных» символов, использующихся внутри самого JavaScript, и мы можем использовать их, чтобы настраивать различные аспекты поведения объектов.
Эти символы перечислены в спецификации в таблице Well-known symbols:
В частности, Symbol.toPrimitive позволяет описать правила для объекта, согласно которым он будет преобразовываться к примитиву. Мы скоро увидим его применение.
С другими системными символами мы тоже скоро познакомимся, когда будем изучать соответствующие возможности языка.
Итого
Символ (symbol) – примитивный тип данных, использующийся для создания уникальных идентификаторов.
Даже если символы имеют одно и то же имя, это – разные символы. Если мы хотим, чтобы одноимённые символы были равны, то следует использовать глобальный реестр: вызов Symbol.for(key) возвращает (или создаёт) глобальный символ с key в качестве имени. Многократные вызовы команды Symbol.for с одним и тем же аргументом возвращают один и тот же символ.
Символы имеют два основных варианта использования:
Так что, используя символьные свойства, мы можем спрятать что-то нужное нам, но что другие видеть не должны.
Базовые операторы, математика
В этой главе мы начнём с простых операторов, а потом сконцентрируемся на специфических для JavaScript аспектах, которые не проходят в школьном курсе арифметики.
Термины: «унарный», «бинарный», «операнд»
Прежде, чем мы двинемся дальше, давайте разберёмся с терминологией.
Унарным называется оператор, который применяется к одному операнду. Например, оператор унарный минус «-» меняет знак числа на противоположный:
Бинарным называется оператор, который применяется к двум операндам. Тот же минус существует и в бинарной форме:
Формально, в последних примерах мы говорим о двух разных операторах, использующих один символ: оператор отрицания (унарный оператор, который обращает знак) и оператор вычитания (бинарный оператор, который вычитает одно число из другого).
Математика
Поддерживаются следующие математические операторы:
Первые четыре оператора очевидны, а про % и ** стоит сказать несколько слов.
Взятие остатка %
Возведение в степень **
В выражении a ** b оператор возведения в степень умножает a на само себя b раз.
Математически, оператор работает и для нецелых чисел. Например, квадратный корень является возведением в степень 1/2 :
Сложение строк при помощи бинарного +
Давайте рассмотрим специальные возможности операторов JavaScript, которые выходят за рамки школьной арифметики.
Обычно при помощи плюса ‘+’ складывают числа.
Но если бинарный оператор ‘+’ применить к строкам, то он их объединяет в одну:
Обратите внимание, если хотя бы один операнд является строкой, то второй будет также преобразован в строку.
Как видите, не важно, первый или второй операнд является строкой.
Вот пример посложнее:
Например, вычитание и деление:
Приведение к числу, унарный +
Плюс + существует в двух формах: бинарной, которую мы использовали выше, и унарной.
Унарный, то есть применённый к одному значению, плюс + ничего не делает с числами. Но если операнд не число, унарный плюс преобразует его в число.
Необходимость преобразовывать строки в числа возникает очень часто. Например, обычно значения полей HTML-формы — это строки. А что, если их нужно, к примеру, сложить?
Бинарный плюс сложит их как строки:
Поэтому используем унарный плюс, чтобы преобразовать к числу:
С точки зрения математика, такое изобилие плюсов выглядит странным. Но с точки зрения программиста тут нет ничего особенного: сначала выполнятся унарные плюсы, которые приведут строки к числам, а затем бинарный ‘+’ их сложит.
Почему унарные плюсы выполнились до бинарного сложения? Как мы сейчас увидим, дело в их приоритете.
Приоритет операторов
В том случае, если в выражении есть несколько операторов – порядок их выполнения определяется приоритетом, или, другими словами, существует определённый порядок выполнения операторов.
Из школы мы знаем, что умножение в выражении 1 + 2 * 2 выполнится раньше сложения. Это как раз и есть «приоритет». Говорят, что умножение имеет более высокий приоритет, чем сложение.
В JavaScript много операторов. Каждый оператор имеет соответствующий номер приоритета. Тот, у кого это число больше, – выполнится раньше. Если приоритет одинаковый, то порядок выполнения – слева направо.
Отрывок из таблицы приоритетов (нет необходимости всё запоминать, обратите внимание, что приоритет унарных операторов выше, чем соответствующих бинарных):
Приоритет | Название | Обозначение |
---|---|---|
… | … | … |
17 | унарный плюс | + |
17 | унарный минус | — |
16 | возведение в степень | ** |
15 | умножение | * |
15 | деление | / |
13 | сложение | + |
13 | вычитание | — |
… | … | … |
3 | присваивание | = |
… | … | … |
Присваивание
Присваивание = возвращает значение
Тот факт, что = является оператором, а не «магической» конструкцией языка, имеет интересные последствия.
Вызов x = value записывает value в x и возвращает его.
Благодаря этому присваивание можно использовать как часть более сложного выражения:
В примере выше результатом (a = b + 1) будет значение, которое присваивается переменной a (то есть 3 ). Потом оно используется для дальнейших вычислений.
Забавное применение присваивания, не так ли? Нам нужно понимать, как это работает, потому что иногда это можно увидеть в JavaScript-библиотеках.
Однако писать самим в таком стиле не рекомендуется. Такие трюки не сделают ваш код более понятным или читабельным.
Присваивание по цепочке
Рассмотрим ещё одну интересную возможность: цепочку присваиваний.
Опять-таки, чтобы код читался легче, лучше разделять подобные конструкции на несколько строчек:
Польза от такого стиля особенно ощущается при быстром просмотре кода.
Сокращённая арифметика с присваиванием
Часто нужно применить оператор к переменной и сохранить результат в ней же.
Эту запись можно укоротить при помощи совмещённых операторов += и *= :
Логические операторы
Несмотря на своё название, данные операторы могут применяться к значениям любых типов. Полученные результаты также могут иметь различный тип.
Давайте рассмотрим их подробнее.
Оператор «ИЛИ» выглядит как двойной символ вертикальной черты:
В JavaScript, как мы увидим далее, этот оператор работает несколько иным образом. Но давайте сперва посмотрим, что происходит с булевыми значениями.
Существует всего четыре возможные логические комбинации:
Если значение не логического типа, то оно к нему приводится в целях вычислений.
Обычно оператор || используется в if для проверки истинности любого из заданных условий.
Можно передать и больше условий:
ИЛИ «||» находит первое истинное значение
Описанная выше логика соответствует традиционной. Теперь давайте поработаем с «дополнительными» возможностями JavaScript.
Расширенный алгоритм работает следующим образом.
При выполнении ИЛИ || с несколькими значениями:
Оператор || выполняет следующие действия:
Значение возвращается в исходном виде, без преобразования.
Другими словами, цепочка ИЛИ «||» возвращает первое истинное значение или последнее, если такое значение не найдено.
Это делает возможным более интересное применение оператора по сравнению с «чистым, традиционным, только булевым ИЛИ».
Получение первого истинного значения из списка переменных или выражений.
Сокращённое вычисление.
Операндами могут быть как отдельные значения, так и произвольные выражения. ИЛИ вычисляет их слева направо. Вычисление останавливается при достижении первого истинного значения. Этот процесс называется «сокращённым вычислением», поскольку второй операнд вычисляется только в том случае, если первого недостаточно для вычисления всего выражения.
Это хорошо заметно, когда выражение, указанное в качестве второго аргумента, имеет побочный эффект, например, изменение переменной.
В приведённом ниже примере x не изменяется:
Присваивание – лишь один пример. Конечно, могут быть и другие побочные эффекты, которые не проявятся, если вычисление до них не дойдёт.
Как мы видим, этот вариант использования || является «аналогом if «. Первый операнд преобразуется в логический. Если он оказывается ложным, начинается вычисление второго.
Оператор И пишется как два амперсанда && :
Форум
Справочник
Операторы, их особенности в JS
В Javascript есть все необходимые для жизни операторы, хотя нет их перегрузки.
Некоторые операторы(+,побитовые,логические,===) имеют специфические особенности.
Арифметические
Унарный оператор «+» также используется для преобразования строки к числу:
Побитовые
Логические
Логическое И. Возвращает последний операнд, если все операнды верны. Если хоть один из операндов неверен, то возвратит первый неверный операнд.
Оператор И обычно используется, чтобы избежать ошибок при получении вложенных свойств объекта.
Например, нужно свойство petShop.animals.rabbit или ложное значение, если такого свойства нет.
выдаст ошибку(бросит исключение) об отсутствующем свойстве.
Оператор логического ИЛИ возвращает первое верное значение. А если верных значений вообще нет, то последнее неверное.
Это удобно использовать так:
Сравнение
Операторы больше-меньше также работают со строками, сравнивая их лексикографически, т.е посимвольно.
Сравнение == делается с приведением типов, а === без приведения типов, например:
Логическое И. Возвращает последний верный операнд
Возвращает последний операнд, если все они верны.
Возвращает последний операнд, если все они верны.
Верно, эффект имеет только использование ||, с && же подобным образом обращение не срабатывает
Спасибо, развернул эту часть статьи чуть пошире.
А как же такой красивый способ преобразования к числу?
var s = ‘7’;
var n = +s;
alert(n.constructor); // Number
Да, интересно себя ведёт оператор
alert(«1″+1) // 11
alert(+»1″+1) // 2
alert(0+»1″+1) // 011
все верно он себя ведет. Ты же не указываешь что данную строку нужно воспринимать как число.
Попробуй так:
и будет тебе щастье
Спасибо!! Очень помог.
«. Сравнение == делается с приведением типов, а === без приведения типов. «. Наверное, наоборот:Сравнение == делается БЕЗ приведения типов, а === С приведения типов
Нет, как раз == с приведением, === без
Мне кто нибудь может подсказать как исчисляется
>>> (Сдвиг вправо с заполнением нулями)
>>>= (Сдвиг вправо с заполнением нулями и присваиванием)
Пытаюсь понять, но никак не получается.
x=13>>>1
x=6
Как они его вычислили, что получилась такая сумма?
Про разряды я то знаю, мне интересно сам ход выполнения операции.
Если я не ошибаюсь и правильно понял:
-8 хранится в обратном коде:
11111111111111111111111111111000 = 4294967288
сдвиг на 2 вправо с доопределением 0 = делению на 4:
00111111111111111111111111111110 = 1073741822
Это я знаю, как исчисляется. Причем двойка(2) в этой формуле обязательна!
у меня есть строка, скажем «2+2*3». как получить результат вычисления (8) из строки, не разбирая её (длина строки не известна, операторы также)?
В Javascript есть все необходимые для жизни операторы, хотя нет их перегрузки.
function Point (x,y) <
this.x = x;
this.y = y;
this.toString = function() <
return «Point( » + this.x + «, » + this.y + » )»;
>
return this;
>
var foo = new Point(2, 3);
alert( «Foo is » + foo ); // Выдаст «Foo is Point( 2, 3 ) «
Здесь в alert() вызывается foo.toString() при складывании foo и «Foo is». Это почти перегрузка оператора приведения типов, как в С++:
#include
#include
#include
using namespace std;
struct Point <
int x, y;
operator const char* () <
stringstream s;
s undefined (а не false, как говорится в статье)
var rabbit = petShop.animals.rabbit;
alert (rabbit);//=>undefined (какой смысл тогда применять прием по поиску свойства в объекте с использованием &&? )
вот еще код к вопросу. просто не могу понять, зачем прием с && при проверке
petShop.animals.rabbit, ведь результат не меняется:
//в чем тогда разница-то? Зачем if (petShop && petShop.animals && petShop.animals.rabbit), а не просто if (petShop.animals.rabbit)
Просьба пояснить, что значит данная конструкция?
var toggle = oldop == ‘upload’;
это инициализация переменной toggle, которая примет булевское значение в зависимости от результата сравнения oldop == ‘upload’ (сравнение будет проведено с приведением типом)
Если чуточку изменить Ваш код, то станет понятней. Я сделал так:
Проверял в консоли браузера. Все очень логично.
Лексический синтаксис
Спецсимволы
Спецсимволы не имеют визуального представления, однако используются для управления интерпретацией текста.
Code point | Name | Abbreviation | Description |
---|---|---|---|
U+200C | Zero width non-joiner | Размещается между символами во избежание их соединений в лигатуры для некоторых языков (Wikipedia) | |
U+200D | Zero width joiner | Размещается между символами, которые не могли бы нормально объединиться для того, чтобы символы отрисовывались, используя их соединительную форму в некоторых языках (Wikipedia) | |
U+FEFF | Byte order mark | Используется вначале скрипта для того, чтобы пометить Юникод и порядок байтов (Wikipedia) |
Пробелы
Пробельные символы улучшают читабельность исходного текста и разделяет токены друг от друга. Пробельные символы обычно не обязательны для функционирования кода. Утилиты для уменьшения объёма кода часто удаляют пробельные символы, чтобы уменьшить объем кода.
Code point | Name | Abbreviation | Description | Escape sequence |
---|---|---|---|---|
U+0009 | Character tabulation | Горизонтальная табуляция | \t | |
U+000B | Line tabulation | Вертикальная табуляция | \v | |
U+000C | Form feed | Символ контроля разрыва страницы (Wikipedia) | \f | |
U+0020 | Space | Обычный пробел | ||
U+00A0 | No-break space | |||
Others | Other Unicode space characters | Другие символы в Юникоде на Википедии |
Окончание строк
В дополнение к пробельным символам, символы окончания строк тоже используются для читабельности исходного кода. Однако, в некоторых случаях, символы окончания строк могут влиять на выполнение JavaScript-кода, т.к. есть некоторые места, где они запрещены.
Окончания строк также затрагивают процесс автоматического проставления точки с запятой. Также окончания строк попадают под условия регулярных выражений при поиске \s класса.
В ECMAScript, в качестве окончания строк можно использовать только ниже перечисленные Юникод символы. Другие символы окончания строк будут интерпретированы, как пробельные символы (например, Next Line, NEL, U+0085 будут интерпретироваться, как пробельные символы).
Code point | Name | Abbreviation | Description | Escape sequence |
---|---|---|---|---|
U+000A | Line Feed | Новая строка в UNIX системах. | \n | |
U+000D | Carriage Return | Новая строка в Commodore и ранних Mac systems. | \r | |
U+2028 | Line Separator | Wikipedia | ||
U+2029 | Paragraph Separator |