JavaScript
В JavaScript существует несколько основных типов данных:
- number
- string
- boolean
- null
- undefined
- object
NUMBER
Все числа в JavaScript, как целые так и дробные, имеют тип Number и хранятся в 64-битном формате IEEE-754, также известном как «double precision».
Способы записи
В JavaScript можно записывать числа не только в десятичной, но и в шестнадцатеричной (начинается с 0x) системе счисления:
alert( 0xFF ); // 255 в шестнадцатиричной системе
Также доступна запись в «научном формате» (ещё говорят «запись с плавающей точкой»), который выглядит как <число>e<количество нулей>.
Например, 1e3 – это 1 с 3 нулями, то есть 1000.
// еще пример научной формы: 3 с 5 нулями
alert( 3e5 ); // 300000
Если количество нулей отрицательно, то число сдвигается вправо за десятичную точку, так что получается десятичная дробь:
// здесь 3 сдвинуто 5 раз вправо, за десятичную точку.
alert( 3e-5 ); // 0.00003 <-- 5 нулей, включая начальный ноль
Деление на ноль, Infinity
При делении на очень-очень маленькое число должно получиться очень большое. В математическом анализе это описывается через пределы, и если подразумевать предел, то в качестве результата деления на 0 мы получаем «бесконечность», которая обозначается символом ∞ (в JavaScript Infinity).
alert( 1 / 0 ); // Infinity
alert( 12345 / 0 ); // Infinity
Infinity – особенное численное значение, которое ведет себя в точности как математическая бесконечность ∞.
-
Infinity больше любого числа.
-
Добавление к бесконечности не меняет её.
alert( Infinity > 1234567890 ); // true
alert( Infinity + 5 == Infinity ); // true
Бесконечность можно присвоить и в явном виде: var x = Infinity.
Бывает и минус бесконечность -Infinity:
alert( -1 / 0 ); // -Infinity
NaN
Если математическая операция не может быть совершена, то возвращается специальное значение NaN (Not-A-Number).
Например, деление 0/0 в математическом смысле неопределено, поэтому его результат NaN:
alert( 0 / 0 ); // NaN
Значение NaN используется для обозначения математической ошибки и обладает следующими свойствами:
-
Значение NaN – единственное в своем роде, которое не равно ничему, включая себя.
Следующий код ничего не выведет:
if (NaN == NaN) alert( "==" ); // Ни один вызов if (NaN === NaN) alert( "===" ); // не сработает -
Значение NaN можно проверить специальной функцией isNaN(n), которая преобразует аргумент к числу и возвращает true, если получилось NaN, и false – для любого другого значения.
-
var n = 0 / 0; alert( isNaN(n) ); // true alert( isNaN("12") ); // false, строка преобразовалась к обычному числу 12 -
Значение NaN «прилипчиво». Любая операция с NaN возвращает NaN.
alert( NaN + 1 ); // NaN
Если аргумент isNaN – не число, то он автоматически преобразуется к числу.
Математические операции в JS безопасны
Никакие математические операции в JavaScript не могут привести к ошибке или «обрушить» программу.
В худшем случае результат будет NaN.
-
Забавный способ проверки на NaN
Отсюда вытекает забавный способ проверки значения на NaN: можно проверить значение на равенство самому себе, если не равно – то NaN:
var n = 0 / 0; if (n !== n) alert( 'n = NaN!' );
Это работает, но для наглядности лучше использовать isNaN(n).
isFinite(n)
Итак, в JavaScript есть обычные числа и три специальных числовых значения: NaN, Infinity и -Infinity.
Тот факт, что они, хоть и особые, но числа, демонстрируется работой оператора +:
var value = prompt("Введите Infinity", 'Infinity'); var number = +value; alert( number ); // Infinity, плюс преобразовал строку "Infinity" к такому "числу"
Обычно если мы хотим от посетителя получить число, то Infinity или NaN нам не подходят. Для того чтобы отличить «обычные» числа от таких специальных значений, существует функция isFinite.
Функция isFinite(n) преобразует аргумент к числу и возвращает true, если это не NaN/Infinity/-Infinity:
alert( isFinite(1) ); // true
alert( isFinite(Infinity) ); // false
alert( isFinite(NaN) ); // false
Преобразование к числу
Большинство арифметических операций и математических функций преобразуют значение в число автоматически.
Для того чтобы сделать это явно, обычно перед значением ставят унарный плюс '+':
var s = "12.34";
alert( +s ); // 12.34
При этом, если строка не является в точности числом, то результат будет NaN:
alert( +"12test" ); // NaN
Единственное исключение – пробельные символы в начале и в конце строки, которые игнорируются:
alert( +" -12" ); // -12
alert( +" \n34 \n" ); // 34, перевод строки \n является пробельным символом
alert( +"" ); // 0, пустая строка становится нулем
alert( +"1 2" ); // NaN, пробел посередине числа - ошибка
Аналогичным образом происходит преобразование и в других математических операторах и функциях:
alert( '12.34' / "-2" ); // -6.17
Мягкое преобразование: parseInt и parseFloat
В мире HTML/CSS многие значения не являются в точности числами. Например метрики CSS: 10pt или -12px.
Оператор '+' для таких значений возвратит NaN:
alert(+"12px") // NaN
Для удобного чтения таких значений существует функция parseInt:
alert( parseInt('12px') ); // 12
Функция parseInt и ее аналог parseFloat преобразуют строку символ за символом, пока это возможно.
При возникновении ошибки возвращается число, которое получилось. Функция parseInt читает из строки целое число, а parseFloat – дробное.
alert( parseInt('12px') ) // 12, ошибка на символе 'p'
alert( parseFloat('12.3.4') ) // 12.3, ошибка на второй точке
Конечно, существуют ситуации, когда parseInt/parseFloatвозвращают NaN. Это происходит при ошибке на первом же символе:
alert( parseInt('a123') ); // NaN
Проверка на число
Для проверки строки на число можно использовать функцию isNaN(str).
Она преобразует строку в число аналогично +, а затем вернёт true, если это NaN, то есть если преобразование не удалось.
Однако, у такой проверки есть две особенности:
- Пустая строка и строка из пробельных символов преобразуются к 0, поэтому считаются числами.
- Если применить такую проверку не к строке, то могут быть сюрпризы, в частности isNaN посчитает числами значения false, true, null, так как они хотя и не числа, но преобразуются к ним.
Если же нужна действительно точная проверка на число, которая не считает числом строку из пробелов, логические и специальные значения, а также отсекает Infinity – используйте следующую функцию isNumeric
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Разберёмся, как она работает. Начнём справа.
-
Функция isFinite(n) преобразует аргумент к числу и возвращает true, если это не Infinity/-Infinity/NaN.
Таким образом, правая часть отсеет заведомо не-числа, но оставит такие значения как true/false/null и пустую строку '', так как они корректно преобразуются в числа.
-
Для их проверки нужна левая часть. Вызов parseFloat(true/false/null/'') вернёт NaN для этих значений.
Так устроена функция parseFloat: она преобразует аргумент к строке, то есть true/false/null становятся "true"/"false"/"null", а затем считывает из неё число, при этом пустая строка даёт NaN.
В результате отсеивается всё, кроме строк-чисел и обычных чисел.
Округление
Одна из самых частых операций с числом – округление. В JavaScript существуют целых 3 функции для этого.
Math.floor
Округляет вниз
Math.ceil
Округляет вверх
Math.round
Округляет до ближайшего целого
alert( Math.floor(3.1) ); // 3
alert( Math.ceil(3.1) ); // 4
alert( Math.round(3.1) ); // 3
Округление битовыми операторами
Битовые операторы делают любое число 32-битным целым, обрезая десятичную часть.
В результате побитовая операция, которая не изменяет число, например, двойное битовое НЕ – округляет его:
alert( ~~12.3 ); // 12
Любая побитовая операция такого рода подойдет, например XOR (исключающее ИЛИ, "^") с нулем:
alert( 12.3 ^ 0 ); // 12
alert( 1.2 + 1.3 ^ 0 ); // 2, приоритет ^ меньше, чем +
Это удобно в первую очередь тем, что легко читается и не заставляет ставить дополнительные скобки как Math.floor(...):
var x = a * b / c ^ 0; // читается как "a * b / c и округлить"
Строки
В JavaScript любые текстовые данные являются строками. Не существует отдельного типа «символ», который есть в ряде других языков.
Внутренним форматом строк, вне зависимости от кодировки страницы, является Юникод (Unicode).
Создание строк
Строки создаются при помощи двойных или одинарных кавычек:
var text = "моя строка";
var anotherText = 'еще строка';
var str = "012345";
В JavaScript нет разницы между двойными и одинарными кавычками.
Строки могут содержать специальные символы. Самый часто используемый из таких символов – это «перевод строки».
Он обозначается как \n, например:
alert( 'Привет\nМир' ); // выведет "Мир" на новой строке
Есть и более редкие символы, вот их список:
Специальные символыСимволОписание
| \b | Backspace |
| \f | Form feed |
| \n | New line |
| \r | Carriage return |
| \t | Tab |
| \uNNNN |
Символ в кодировке Юникод с шестнадцатеричным кодом `NNNN`. Например, `\u00A9` -- юникодное представление символа копирайт © |
Если строка в одинарных кавычках, то внутренние одинарные кавычки внутри должны быть экранированы, то есть снабжены обратным слешем \', вот так:
var str = 'I\'m a JavaScript programmer';
В двойных кавычках – экранируются внутренние двойные:
var str = "I'm a JavaScript \"programmer\" ";
alert( str ); // I'm a JavaScript "programmer"
Экранирование служит исключительно для правильного восприятия строки JavaScript. В памяти строка будет содержать сам символ без '\'. Вы можете увидеть это, запустив пример выше.
Сам символ обратного слэша '\' является служебным, поэтому всегда экранируется, т.е пишется как \\:
var str = ' символ \\ ';
alert( str ); // символ \
Заэкранировать можно любой символ. Если он не специальный, то ничего не произойдёт:
alert( "\a" ); // a
// идентично alert( "a" );
Экранирование служит исключительно для правильного восприятия строки JavaScript. В памяти строка будет содержать сам символ без '\'. Вы можете увидеть это, запустив пример выше.
Сам символ обратного слэша '\' является служебным, поэтому всегда экранируется, т.е пишется как \\:
var str = ' символ \\ ';
alert( str ); // символ \
Заэкранировать можно любой символ. Если он не специальный, то ничего не произойдёт:
alert( "\a" ); // a
// идентично alert( "a" );
Булевый (логический) тип «boolean»
У него всего два значения: true (истина) и false (ложь).
Как правило, такой тип используется для хранения значения типа да/нет, например:
var checked = true; // поле формы помечено галочкой
checked = false; // поле формы не содержит галочки
Специальное значение «null»
Значение null не относится ни к одному из типов выше, а образует свой отдельный тип, состоящий из единственного значения null:
var age = null;
В JavaScript null не является «ссылкой на несуществующий объект» или «нулевым указателем», как в некоторых других языках. Это просто специальное значение, которое имеет смысл «ничего» или «значение неизвестно».
В частности, код выше говорит о том, что возраст age неизвестен.
Специальное значение «undefined»
Значение undefined, как и null, образует свой собственный тип, состоящий из одного этого значения. Оно имеет смысл «значение не присвоено».
Если переменная объявлена, но в неё ничего не записано, то её значение как раз и есть undefined:
var x;
alert( x ); // выведет "undefined"
Можно присвоить undefined и в явном виде, хотя это делается редко:
var x = 123;
x = undefined;
alert( x ); // "undefined"
В явном виде undefined обычно не присваивают, так как это противоречит его смыслу. Для записи в переменную «пустого» или «неизвестного» значения используется null.
Объекты «object»
Первые 5 типов называют «примитивными».
Особняком стоит шестой тип: «объекты».
Он используется для коллекций данных и для объявления более сложных сущностей.
Объявляются объекты при помощи фигурных скобок {...}, например:
var user = { name: "Вася" };
Оператор typeof
Оператор typeof возвращает тип аргумента.
У него есть два синтаксиса: со скобками и без:
- Синтаксис оператора: typeof x.
- Синтаксис функции: typeof(x).
Работают они одинаково, но первый синтаксис короче.
Результатом typeof является строка, содержащая тип:
typeof undefined // "undefined"
typeof 0 // "number"
typeof true // "boolean"
typeof "foo" // "string"
typeof {} // "object"
typeof null // "object" (1)
typeof function(){} // "function" (2)
Последние две строки помечены, потому что typeof ведет себя в них по-особому.
- Результат typeof null == "object" – это официально признанная ошибка в языке, которая сохраняется для совместимости. На самом деле null – это не объект, а отдельный тип данных.
- Функции мы пройдём чуть позже. Пока лишь заметим, что функции не являются отдельным базовым типом в JavaScript, а подвидом объектов. Но typeof выделяет функции отдельно, возвращая для них "function". На практике это весьма удобно, так как позволяет легко определить функцию.
Функции
Зачастую нам надо повторять одно и то же действие во многих частях программы.
Например, красиво вывести сообщение необходимо при приветствии посетителя, при выходе посетителя с сайта, ещё где-нибудь.
Чтобы не повторять один и тот же код во многих местах, придуманы функции. Функции являются основными «строительными блоками» программы.
Примеры встроенных функций вы уже видели – это alert(message), prompt(message, default) и confirm(question). Но можно создавать и свои.
Объявление
Пример объявления функции:
function showMessage() {
alert( 'Привет всем присутствующим!' );
}
Вначале идет ключевое слово function, после него имя функции, затем список параметров в скобках (в примере выше он пустой) и тело функции – код, который выполняется при её вызове.
Объявленная функция доступна по имени, например:
function showMessage() {
alert( 'Привет всем присутствующим!' );
}
showMessage();
showMessage();
Этот код выведет сообщение два раза. Уже здесь видна главная цель создания функций: избавление от дублирования кода.
Локальные переменные
Функция может содержать локальные переменные, объявленные через var. Такие переменные видны только внутри функции:
function showMessage() {
var message = 'Привет, я - Вася!'; // локальная переменная
alert( message );
}
showMessage(); // 'Привет, я - Вася!'
alert( message ); // <-- будет ошибка, т.к. переменная видна только внутри
Блоки if/else, switch, for, while, do..while не влияют на область видимости переменных.
При объявлении переменной в таких блоках, она всё равно будет видна во всей функции.
цикл
function count() {
// переменные i,j не будут уничтожены по окончании цикла
for (var i = 0; i < 3; i++) {
var j = i * 2;
}
alert( i ); // i=3, последнее значение i, при нём цикл перестал работать
alert( j ); // j=4, последнее значение j, которое вычислил цикл
}
Неважно, где именно в функции и сколько раз объявляется переменная. Любое объявление срабатывает один раз и распространяется на всю функцию.
Объявления переменных в примере выше можно передвинуть вверх, это ни на что не повлияет:
function count() {
var i, j; // передвинули объявления var в начало
for (i = 0; i < 3; i++) {
j = i * 2;
}
alert( i ); // i=3
alert( j ); // j=4
}
Внешние переменные
Функция может обратиться ко внешней переменной, например:
var userName = 'Вася';
function showMessage() {
var message = 'Привет, я ' + userName;
alert(message);
}
showMessage(); // Привет, я Вася
Доступ возможен не только на чтение, но и на запись. При этом, так как переменная внешняя, то изменения будут видны и снаружи функции:
var userName = 'Вася';
function showMessage() {
userName = 'Петя'; // (1) присвоение во внешнюю переменную
var message = 'Привет, я ' + userName;
alert( message );
}
showMessage();
alert( userName ); // Петя, значение внешней переменной изменено функцией
Внимание: неявное объявление глобальных переменных!
В старом стандарте JavaScript существовала возможность неявного объявления переменных присвоением значения.
Например:
function showMessage() {
message = 'Привет'; // без var!
}
showMessage();
alert( message ); // Привет
В коде выше переменная message нигде не объявлена, а сразу присваивается. Скорее всего, программист просто забыл поставить var.
При use strict такой код привёл бы к ошибке, но без него переменная будет создана автоматически, причём в примере выше она создаётся не в функции, а на уровне всего скрипта.
Избегайте этого.
При вызове функции ей можно передать данные, которые та использует по своему усмотрению.
Например, этот код выводит два сообщения:
function showMessage(from, text) { // параметры from, text
from = "** " + from + " **"; // здесь может быть сложный код оформления
alert(from + ': ' + text);
}
showMessage('Маша', 'Привет!');
showMessage('Маша', 'Как дела?');
Параметры копируются в локальные переменные функции.
Например, в коде ниже есть внешняя переменная from, значение которой при запуске функции копируется в параметр функции с тем же именем. Далее функция работает уже с параметром:
function showMessage(from, text) {
from = '**' + from + '**'; // меняем локальную переменную from
alert( from + ': ' + text );
}
var from = "Маша";
showMessage(from, "Привет");
alert( from ); // старое значение from без изменений, в функции была изменена копия
Аргументы по умолчанию
Функцию можно вызвать с любым количеством аргументов.
Если параметр не передан при вызове – он считается равным undefined.
Например, функцию показа сообщения showMessage(from, text)можно вызвать с одним аргументом:
showMessage("Маша");
При этом можно проверить, и если параметр не передан – присвоить ему значение «по умолчанию»:
function showMessage(from, text) {
if (text === undefined) {
text = 'текст не передан';
}
alert( from + ": " + text );
}
showMessage("Маша", "Привет!"); // Маша: Привет!
showMessage("Маша"); // Маша: текст не передан
При объявлении функции необязательные аргументы, как правило, располагают в конце списка.
Для указания значения «по умолчанию», то есть, такого, которое используется, если аргумент не указан, используется два способа:
-
Можно проверить, равен ли аргумент undefined, и если да – то записать в него значение по умолчанию. Этот способ продемонстрирован в примере выше.
-
Использовать оператор ||:
function showMessage(from, text) { text = text || 'текст не передан'; ... }Второй способ считает, что аргумент отсутствует, если передана пустая строка, 0, или вообще любое значение, которое в логическом контексте является false.
Если аргументов передано больше, чем надо, например showMessage("Маша", "привет", 1, 2, 3), то ошибки не будет. Но, чтобы получить такие «лишние» аргументы, нужно будет прочитать их из специального объекта arguments.
Возврат значения
Функция может возвратить результат, который будет передан в вызвавший её код.
Например, создадим функцию calcD, которая будет возвращать дискриминант квадратного уравнения по формуле b2 – 4ac:
function calcD(a, b, c) {
return b*b - 4*a*c;
}
var test = calcD(-4, 2, 1);
alert(test); // 20
Для возврата значения используется директива return.
Она может находиться в любом месте функции. Как только до неё доходит управление – функция завершается и значение передается обратно.
function checkAge(age) { if (age > 18) { return true; } else { return confirm('Родители разрешили?'); } } var age = prompt('Ваш возраст?'); if (checkAge(age)) { alert( 'Доступ разрешен' ); } else { alert( 'В доступе отказано' ); }
Директива return может также использоваться без значения, чтобы прекратить выполнение и выйти из функции.
function showMovie(age) {
if (!checkAge(age)) {
return;
}
alert( "Фильм не для всех" ); // (*)
// ...
}
В коде выше, если сработал if, то строка (*) и весь код под ней никогда не выполнится, так как return завершает выполнение функции.
Вызовов return может быть и несколько, например:
Значение функции без return и с пустым return
В случае, когда функция не вернула значение или return был без аргументов, считается что она вернула undefined:
function doNothing() { /* пусто */ }
alert( doNothing() ); // undefined
Обратите внимание, никакой ошибки нет. Просто возвращается undefined.
Ещё пример, на этот раз с return без аргумента:
function doNothing() {
return;
}
alert( doNothing() === undefined ); // true
Выбор имени функции
Имя функции следует тем же правилам, что и имя переменной. Основное отличие – оно должно быть глаголом, т.к. функция – это действие.
Как правило, используются глагольные префиксы, обозначающие общий характер действия, после которых следует уточнение.
Функции, которые начинаются с "show" – что-то показывают:
showMessage(..) // префикс show, "показать" сообщение
Функции, начинающиеся с "get" – получают, и т.п.:
getAge(..) // get, "получает" возраст
calcD(..) // calc, "вычисляет" дискриминант
createForm(..) // create, "создает" форму
checkPermission(..) // check, "проверяет" разрешение, возвращает true/false
Это очень удобно, поскольку взглянув на функцию – мы уже примерно представляем, что она делает, даже если функцию написал совсем другой человек, а в отдельных случаях – и какого вида значение она возвращает.
Одна функция – одно действие
Функция должна делать только то, что явно подразумевается её названием. И это должно быть одно действие.
Если оно сложное и подразумевает поддействия – может быть имеет смысл выделить их в отдельные функции? Зачастую это имеет смысл, чтобы лучше структурировать код.
…Но самое главное – в функции не должно быть ничего, кроме самого действия и поддействий, неразрывно связанных с ним.
Например, функция проверки данных (скажем, "validate") не должна показывать сообщение об ошибке. Её действие – проверить.
Сверхкороткие имена функций
Имена функций, которые используются очень часто, иногда делают сверхкороткими.
Например, во фреймворке jQuery есть функция $, во фреймворке Prototype – функция $$, а в библиотеке LoDashочень активно используется функция с названием из одного символа подчеркивания _.
Итого
Объявление функции имеет вид:
function имя(параметры, через, запятую) {
код функции
}
- Передаваемые значения копируются в параметры функции и становятся локальными переменными.
- Параметры функции копируются в её локальные переменные.
- Можно объявить новые локальные переменные при помощи var.
- Значение возвращается оператором return ....
- Вызов return тут же прекращает функцию.
- Если return; вызван без значения, или функция завершилась без return, то её результат равен undefined.
При обращении к необъявленной переменной функция будет искать внешнюю переменную с таким именем, но лучше, если функция использует только локальные переменные:
- Это делает очевидным общий поток выполнения – что передаётся в функцию и какой получаем результат.
- Это предотвращает возможные конфликты доступа, когда две функции, возможно написанные в разное время или разными людьми, неожиданно друг для друга меняют одну и ту же внешнюю переменную.
Именование функций:
- Имя функции должно понятно и чётко отражать, что она делает. Увидев её вызов в коде, вы должны тут же понимать, что она делает.
- Функция – это действие, поэтому для имён функций, как правило, используются глаголы.
Функции являются основными строительными блоками скриптов. Мы будем неоднократно возвращаться к ним и изучать все более и более глубоко.
javaScript, типы данных
By pavel_efimov
javaScript, типы данных
- 331