• JavaScript Типы данных. Типы данных Java Script Переменные и типы данных javascript

    Начнем, как обычно, с определения того, с чем мы знакомимся. Что же такое типы данных? Это понятие относится ко всем языкам программирования и JavaScript здесь не уникален. Если мы обратимся к определению в Википедии, то узнаем, что типы данных — это множество значений и операций на этих значениях. Говоря проще, тип данных это, по сути, тип значений, которые мы можем сохранить в переменную и работать с ними.

    В статье о переменных в JavaScript мы сравнили переменную с коробкой, в которую можно положить что угодно. Собственно, это что угодно и есть значение любого типа данных. Даже если вы не знакомы ни с одним языком программирования, интуитивно, думаю, вы уже сейчас сможете назвать как минимум два типа данных, которые есть в JavaScript. Правильно, это число и строка или строковый и числовой тип данных. Помните, мы записывали в переменную и строки, и числа? Разница лишь в том, что строку мы обязаны были заключить в кавычки.

    Итак, в JavaScript можно выделить шесть типов данных:

    JavaScript. Быстрый старт

    логическое или булево значение

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

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

    var name = "John", surname = "Doe";

    var name = "John" ,

    surname = "Doe" ;

    JavaScript. Быстрый старт

    Изучите основы JavaScript на практическом примере по созданию веб-приложения

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

    var num1 = 2, num2 = 3.4 num3 = -5;

    var num1 = 2 ,

    num2 = 3.4

    num3 = - 5 ;

    Обратите внимание, дробная часть числа отделяется не запятой, а точкой (десятичная точка). Также число может быть со знаком: -5 в примере.

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

    Итак, логический тип или булев тип данных. У него всего два возможных значения: true и false. Если упростить, то их можно сравнить с словами «да» и «нет» или «истина» и «ложь». Пример записи булевых значений в JavaScript:

    var yes = true, no = false;

    var yes = true ,

    no = false ;

    Обратите внимание, значения true и false регистрозависимы. В PHP, к примеру, константы true и false не зависят от регистра.

    Следующие два специальных значения — null и undefined. Они очень похожи и по сути обозначают одно и то же — отсутствие значения. undefined будет значением переменной, которая просто объявлена, но для нее не установлено значение, т.е. значение не определено. null же часто записывают в переменную, чтобы обнулить значение переменной, сделать его неизвестным, если можно так сказать. В следующих статьях мы детальнее увидим специфику работы с этими типами данных в JavaScript.

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

    // запись объекта var user = { name: "John", surname: "Doe", year: 2016 }; // обращение к свойствам объекта alert(user.name); alert(user.surname); alert(user.year);

    Переменные в JavaScript объявляются с помощью ключевого слова var , например:

    После этого можно задать значение переменной:

    x = “Sample string”;

    Язык JavaScript позволяет создавать переменные «на лету» без их объявления, например:

    y = “Second string”;

    При этом переменная y будет создана, и в памяти будет отведено для нее место, однако такая практика затрудняет чтение и отладку скрипта.

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

    JavaScript поддерживает пять базовых типов данных: Number – числа; String – строки; Boolean – Булев тип; Undefined – неопределенный; Null – пустой. Эти пять типов данных называются базовыми, т.к. на основе их строятся более сложные типы данных. Фактический интерес с точки зрения хранения данных представляют три: числа, строки и логические значения, неопределенный и пустой типы представляют интерес в определенных ситуациях.

    Числа

    В языке JavaScript численный тип данных включает целые и вещественные числа. Целые числа могут принимать значения от –2 53 до 2 53 , вещественные могут принимать большие значения в пределах ±1.7976 x 10 308 или быть точными в пределах ±2.2250 x 10 -308 .

    Числа также могут записываться в экспоненциальной форме.

    Для записи целого шестнадцатеричного числа в начале ставится ноль, затем буква x , затем само число, которое может содержать цифры от 0 до 9 и буквы от A до F .

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

    В языке JavaScript также имеется возможность записи чисел в восьмеричной системе счисления: для записи числа в начале ставится 0 , затем идут цифры от 0 до 7 .

    Специальные числа

    Если результат математической операции выходит за допустимые пределы, переменная принимает значение Infinity – бесконечность. При совершении любых операций над таким числом результатом будет бесконечность. При сравнении положительная бесконечность всегда больше любого действительного числа, и наоборот, отрицательная бесконечность всегда меньше любого действительного числа.

    Еще одним важным специальным значением является NaN – «не число» (not a number). Типичным примером операции, которая возвращает NaN , является деле­ние на ноль. Для определения, является ли значение переменной NaN , используется функция isNaN() , которая возвращает true , если число является действии­тельным (включая бесконечность), и false , если значение переменной NaN .

    К специальным числам относятся максимальное и минимальное значения, кото­рые может принимать переменная. Все специальные числа приведены в таблице:

    Строки

    Строка – это последовательность символов огрниченная двойными или одинарными кавычками.

    После создания строки она имеет одно свойство – length , возвращающее длину строки, и большое количество методов:

    charAt (index : Number) : String – возвращает символ, находящийся на определенной позиции;

    concat ([string1 : String [, [, stringN : String]]]]) : String – соединяет строки (аналогично оператору «+»);

    indexOf (subString : String [, startIndex : Number]) : Number – возвращает номер вхождения подстроки в строку, необязательным параметром является номер символа, с которого начинается поиск. Если подстрока не найдена, возвращается -1 . Поиск выполняется слева направо, для поиска справа налево используется метод lastIndexOf() , который имеет аналогичный синтаксис;

    replace (rgExp : RegExp, replaceText : String) : String – выполняет замену регулярного выражения строкой;

    split ([ separator : { String | RegExp } [, limit : Number]]) : Array – разбивает строку на массив подстрок. В качестве первого параметра передается разделитель, на основе которого производится разбиение, если разделитель не указан, возвращается массив, содержащий один элемент с исходной строкой. Второй параметр определяет максимальное количество элементов в возвращаемом массиве;

    substr (start : Number [, length : Number]) : String – возвращает подстроку, которая начинается с определенной позиции и имеет определенную длину;

    substring (start : Number, end : Number) : String – возвращает подстроку, которая начинается и заканчивается в позициях, определенных параметрами.

    Булев тип

    Переменные булевого типа могут принимать одно из двух значения: true – истина; false – ложь. Переменные булевого типа часто используются в условном операторе if . Пример:

    var doAlert = true;

    if (doAlert) { alert(“Hello, World!”); }

    Переменные типа Undefined и Null

    Тип Undefined используется для несуществующих переменных или переменных, значения которых еще не определены. В следующем примере переменная x будет иметь значение Undefined – то есть не определена.

    Тип Null означает пустое значение. Пример объявления пустой переменной:

    Массивы

    В JavaScript массив – это упорядоченная коллекция различных данных. Все элементы массива пронумерованы, первый элемент массива имеет нулевой индекс. Доступ к определенному элементу массива осуществляется с помощью квадратных скобок и номера этого элемента. Пример:

    myArr = “Hello!”;

    Объявление пустого массива и массива, содержащего данные:

    var emptyArr = ;

    var filledArr = ["Hello", "World"];

    Массивы могут быть многомерными. Объявление и обращение к многомерному массиву выглядит так:

    var myArr = [,,];

    //создается массив размером 3х2 и выводится элемент, содержащийся
    в третьей строке, во втором столбце, равный 6.

    Так как по своей сути массив представляет собой объект, его можно объявлять следующим образом.

    В JavaScript значения достаточно свободно (явно и неявно) могут быть преобразованы из одного типа в другой. Например, если какой-нибудь оператор ожидает получить значение определённого типа, а ему передаётся значение другого типа, то интерпретатор автоматически попытается выполнить преобразования к нужному типу:

    Console.log(10 + " машин"); // "10 машин". Число неявно преобразуется в строку console.log("7" * "4"); // 28. Обе строки неявно преобразуются в числа

    Неявное преобразование - это когда интерпретатор автоматически выполняет преобразование типов, т. е. без участия программиста. Явное преобразование - это когда преобразование выполняет сам программист. Явное преобразование иначе называют приведением типов :

    Console.log("7" * "4"); // 28. Неявное преобразование console.log(Number("7") * Number("4")); // 28. Явное преобразование

    В таблице ниже описывается, как в JavaScript выполняется преобразование значений из одного типа в другой. Пустые ячейки соответствуют ситуациям, когда преобразование не требуется:

    Значение Преобразование в:
    Строку Число Булево Объект
    undefined
    null
    "undefined"
    "null"
    NaN
    0
    false
    false
    ошибка typeError
    ошибка typeError
    true
    false
    "true"
    "false"
    1
    0
    new Boolean(true)
    new Boolean(false)
    "" (пустая строка)
    "1.2"
    "one"
    "-10"
    "+10"
    "011"
    "0xff"
    0
    1.2
    NaN
    -10
    10
    11
    255
    false
    true
    true
    true
    true
    true
    true
    new String("")
    new String("1.2")
    new String("one")
    new String("-10")
    new String("+10")
    new String("011")
    new String("0xff")
    0
    -0
    NaN
    Infinity
    -Infinity
    3
    "0"
    "0"
    "NaN"
    "Infinity"
    "-Infinity"
    "3"
    false
    false
    false
    true
    true
    true
    new Number(0)
    new Number(-0)
    new Number(NaN)
    new Number(Infinity)
    new Number(-Infinity)
    new Number(3)
    {} (любой объект)

    (пустой массив)
    (1 числовой элемент)
    arr (любой другой массив)
    function(){} (любая функция)

    см. Преобразование объектов

    ""
    "9"
    см. Преобразование объектов
    см. Преобразование объектов

    см. Преобразование объектов
    0
    9
    NaN
    NaN
    true

    true
    true
    true
    true

    Для явного преобразования в простые типы используются следующие функции: Boolean() , Number() , String() . При неявном преобразования интерпретатор использует те же функции, что используются для явного преобразования.

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

    X + "" // То же, что и String(x) +x // То же, что и Number(x). Можно также встретить x - 0 !!х // То же, что и Boolean(x)

    Преобразование в числа

    Функция Number() преобразует значения по следующим правилам:

    • Логические значения true и false преобразуются в 1 и 0 соответственно.
    • Числа возвращаются без изменения.
    • Значение null преобразуется в 0 .
    • Значение undefined преобразуется в NaN .

    Для строк действуют особые правила:

    • Если строка содержит только цифры с начальным знаком + или - либо без знака, она всегда преобразуется в целое десятичное число. Начальные нули игнорируются, например "0011" преобразуется в 11.
    • Если строка представляет собой число с плавающей точкой с начальным знаком + или - либо без знака, она преобразуется в соответствующее число с плавающей точкой (начальные нули также игнорируются).
    • Если строка представляет собой число в шестнадцатеричном формате, она преобразуется в соответствующее целое десятичное число.
    • Если строка пустая, она преобразуется в 0 .
    • Если строка содержит что-то отличное от предыдущих вариантов, она преобразуется в NaN .
    • Для объектов вызывается метод valueOf() , а возвращаемое им значение автоматически преобразуется по предыдущим правилам. Если это преобразование даёт в результате NaN , вызывается метод toString() и применяются правила преобразования строк в числа.

    Унарные операторы + и - работают по тем же правилам, что и функция Number() .

    Преобразование в булевы значения

    Функция Boolean() преобразует значение в его логический эквивалент:

    • Следующие значения в результате преобразования дают значение false: undefined , null , 0 , -0 , NaN , "" .
    • Значение false возвращается без изменения.
    • Все остальные значения в результате преобразования дают значение true .

    Преобразование в строки

    Функция String() преобразует значения по следующим правилам:

    • Для всех значений кроме null и undefined автоматически вызывается метод toString() и возвращается строковое представление значения.
    • Для значения null возвращается строка "null" .
    • Для значения undefined возвращается строка "undefined" .

    Преобразование простых типов в объекты

    Для преобразования простых значений в объекты используются конструкторы Boolean() , Number() , String() :

    Var oNum = new Number(3); var oStr = new String("1.2"); var oBool = new Boolean(true); alert(typeof oNum); // "object" alert(typeof oStr); // "object" alert(typeof oBool); // "object"

    Преобразование объектов в простые значения

    Все объекты наследуют два метода преобразования: toString() и valueOf() .

    Метод toString() возвращает строковое представление объекта. По умолчанию он ничего интересного не возвращает:

    Alert({x: 1}.toString()); // ""

    Некоторые типы имеют более специализированные версии метода toString() . Например, метод toString() у массива преобразует все его элементы в строки и затем объединяет их в одну строку, вставляя запятые между ними:

    Alert(.toString()); // "1,2,3"

    Задача метода valueOf() определена не так чётко: предполагается, что он должен преобразовать объект в представляющее его простое значение, если такое значение существует. Объекты по своей сути являются составными значениями, и большинство объектов не могут быть представлены в виде единственного простого значения, поэтому по умолчанию метод valueOf() возвращает не простое значение, а ссылку на него:

    Alert(typeof {x:2}.valueOf()); // "object"

    При преобразовании объекта в строку интерпретатор JavaScript выполняет следующие действия:

    • Если объект имеет метод toString() , интерпретатор вызывает его. Если он возвращает простое значение, интерпретатор преобразует значение в строку (если оно не является строкой) и возвращает результат преобразования.
    • Если объект не имеет метода toString() или этот метод не возвращает простое значение, то интерпретатор проверяет наличие метода valueOf() . Если этот метод определён, интерпретатор вызывает его. Если он возвращает простое значение, интерпретатор преобразует это значение в строку (если оно не является строкой) и возвращает результат преобразования.

    При преобразовании объекта в число интерпретатор выполняет те же действия, но первым пытается применить метод valueOf() :

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

    Методы toString() и valueOf() доступны для чтения и записи, поэтому их можно переопределить и явно указать, что будет возвращаться при преобразовании:

    Var obj = {}; obj.toString = function() { return "объект"; }; alert("Это " + obj); // "Это объект"

    Я решил написать цикл статей, под названием «Сложно о простом». Этот цикл будет посвящён языку JavaScript. Почему «сложно о простом»? Потому что всё, что я буду рассказывать я буду рассказывать учитывая особенности работы интерпретатора, начиная с типов данных. Всё это будет делаться для того, что бы потом можно было рассказать просто о сложном, например, о способах наследования в JavaScript и прочих патернах.

    JavaScript – это объектно-ориентированный язык программирования, с прототипной организацией.
    Что значит «с прототипной организацией», мы поговорим в следующей статье (она обязательно будет), а вот почему он «объектно-ориентированный» и всё ли в JS - объект, мы узнаем сегодня.
    Для выполнения своих целей JS`у достаточно всего 9 типов. Причём только 6 из них доступны программе, оставшиеся же 3 доступны лишь на уровне реализации и используется спецификацией. На первый взгляд(и это первое заблуждение) всё в JS является объектами. Так вот пять из шести доступных программе типов являются так называемыми примитивами и не есть объектами(ниже я поясню почему и как их путают с объектами). Эти пять примитивов это:

    - String (s=’str’)
    - Number (n=10)
    - Boolean (b=true)

    И как я их называю «философские типы»:
    - null (v = null)
    - undefined (u=undefined)

    Философские по тому, что null означает, что переменной присвоено ничего, а undefined – означает, что в переменную присвоили пустоту. Чем отличается «ничего» от «пустоты» в данном случае – поразмыслите на досуге. Сейчас мы этого делать не станем.

    Шестой, доступный программе тип(объектный) – это:
    - Object (не путайте с конструктором Object, мы сейчас ведём речь лишь об абстрактных типах!) – единственный тип, представляющий объекты в JavaScript.
    Объект - это структура данных(целый их набор), представленный в виде набора пар «ключ-значение». Значением может быть любой из типов данных - тогда это будет свойство объекта, или даже функция - тогда это будет метод объекта.

    Есть превеликое множество способов работы с примитивами. Начиная тем, что их можно присвоить в переменные через литералы или через конструкторы и заканчивая тем, что примитивы можно вовсе не объявлять в переменные, работая с ними на прямую. Так же примитивы могут быть в глобальных переменных и в локальных.

    Вот несколько примеров:

    Var v1; //undefined (пустая) локальная переменная var v2="2"; //строковая локальная литеральная переменная var v3 = new String(2); //строковая локальная, объявленная через конструктор переменная. Создаст новый объект типа String v4 = String(2); //строковая глобальная переменная вызванная через конструктор. Создаст переменную window.v4 "2".length; // строка не станет переменной но её можно уже использовать как Объект 34..toString(); //число не станет переменной но его уже можно использовать как объект 12. toString(); //число не станет переменной но его уже можно использовать как объект (22).toString();//число не станет переменной но его уже можно использовать как объект

    В последних 4-х командах, как раз хорошо видно как примитив путают с объектом – ведь мы же вызываем метод, через точку – прямо как у объекта. Действительно создаётся впечатление, что эти примитивы – объекты.

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

    Var v = null; typeof v;

    И получаем в ответ «object».

    А если мы напишем:
    var v = null; v instanceof Object;

    То в голове вообще возникнет каша, потому, что результат последней строчки будет «false». То есть переменная v имеет тип object, но не унаследована от типа Object. Что за дела?!

    Для начала объясню подвох с typeof null. Этот оператор возвращает тип объекта. А дело в том, что оператор typeof возвращает строковое значение, взятое из жёстко закреплённой таблицы, где прописано: «для null – возвращать «object»». Оператор же instanceof – проверяет принадлежит ли что-то к указанному типу данных. Как он это делает, я расскажу в следующей статье, но, уверяю вас, в данном случае он отработал верно, примитив null ни в коем случае не унаследован от типа Object – он сам по себе, примитив – низшая ступень развития.

    Ладно, с typeof и instanceof разобрались, но методы то у примитивов вызываются – как у объектов прям! Как, если это не объект?

    Тут дело вот в чём. Существует такая вещь как функции-обёртки(конструкторы)(и снова всё прояснится во второй статье). Они есть для всех примитивов (Number(), Boolean(), String()), а так же и другие. Их суть состоит в том, что бы из примитива создать объект, у которого будут вспомогательные методы для работы с данным типом примитива.
    Например переменную можно создать так:

    Var num = new Number(23.456);

    В таком случае из примитива 23.456 мы получим объект.
    Для типа number конструктор Number() имеет вспомогательный метод toPrecision() – он определяет для числа количество значимых цифр. Например, если числу 23.456 установить количество значимых цифр 4, то мы получим число 23.45.
    И вот когда мы пытаемся обратится к примитиву как к объекту:

    (23.456). toPrecision(4);

    Интерпретатор временно оборачивает, примитив в объект вызовом new Number(23.456) и потом уже у этого объекта вызывает метод toPrecision(), который у него теперь есть. Таким образом, многие ошибочно считают, что всё в JS есть объектом.

    Так же есть ещё один пример вводящий в заблуждение и вызывающий недопонимание происходящего. Вот код:

    Var str = ‘str’; str.test = ‘test’; //ошибки не будет, программа продолжит работать, но console.log(str.test); //undefined

    Если бы мы считали, как раньше, что str – это объект, мы бы удивились, почему он не запомнил в себе новое свойство test. Но теперь мы знаем, что при обращении к примитиву как к объекту, он временно оборачивается в объект типа String. Но после выполнения операции эта обёртка исчезает, а вместе с ней и новое свойство test. Вот и всё, никакой магии.

    На самом деле, забегая наперёд, во время оборачивания примитива в объект, выстраивается целая цепочка наследования (как это организовано мы поговорим позже), но по сути получается такая вот «матрёшка»:

    Object(Number(<примитив>)). Родителем любого объекта в JS, так или иначе, будет Object. При вызове свойства в объекте поиск проходит по всей этой «матрёшке» пока не найдёт в одном из объектов это свойство или вернёт undefined или если искали метод, то выбросит исключение. Таким образом, у примитива также доступны свойства объекта Object. Как работает прототипное наследование и о его тонкостях мы поговорим во второй статье.

    Для интриги над второй статьёй, которую я хочу выпустить, расскажу про ещё один момент связанный с функциями конструкторами - это преобразование типов. JS - это не строго типизированный язык. Это значит, что в момент объявления переменной мы не обязаны указать какого она типа, и более того во время работы программы в эту переменную можно ложить данные абсолютного любого типа. А так же мы можем использовать, например, строковые переменные в математических действиях или наоборот, числа в операции конкатенации. Пример:

    Var str = "abc"; str+1; // "abc1"

    Здесь примитив типа number - 1, будет преобразован в строковый примитив. В объектах эта возможность доступна через вызов метода toString(), в объектах типа number, есть метод valueOf(), который вернёт примитив типа number. Но мы вроде как говорили что методы могут быть только у объектов. Значит в процессе преобразования примитива из одного типа в другой, происходит тоже оборачивание в объект? Уверяю вас что нет. Вызов этого метода происходит не явно, когда функция-конструктор вызывается интерпретатором без оператора new. Что за волшебный оператор new и что происходит когда функция-конструктор вызывается без него, да и что блин в конце то концов за функция-конструктор такая, мы поговорим в следующей статье. Пока поверьте мне на слово - преобразование типов происходит сразу - из примитива в примитив.

    Пока, конечно, больше вопросов чем ответов, однако, поверьте, всё станет намного прозрачнее после прочтения второй статьи. Здесь я в основном заинтриговал и поднял ряд вопросов - так сказать взбудоражил умы. Но всё же кое-что можно вынести и из этой статьи:
    1. Не смотря на расхожее мнение «всё в JS является объектами» - это не так, мы выяснили, что из 6 доступных программисту типов данных аж 5 является примитивами и лишь один представляет тип объектов.
    2. Про объекты мы узнали, что это такая структура данных, которая содержит в себе пары «ключ-значение». При значением может быть любой из типов данных (и это будет свойство объекта) или функция (и это будет метод объекта).
    3. А вот примитивы – это не объекты. Хотя с ними и можно работать как с объектом (и это вызывает заблуждение что примитив – это объект), но…
    4. Переменные можно объявить как по простому (литерально) (var a = ‘str’), так и через функцию-конструктор (обёртка)(var a = new String(‘str’)). Во втором случае мы получим уже не примитив, а объект созданный функцией-обёрткой String(). (что за магический оператор new и что такое функция-конструктор мы узнаем дальше).
    5. Узнали, что именно за счёт создания обёртки над примитивом (new String(‘str’)) c ним можно работать как с объектом. Именно эту обёртку создаёт интерпретатор вокруг примитива, когда мы пытаемся работать с ним как с объектом, но после выполнения операции она разрушается (поэтому примитив никогда не сможет запомнить свойство, которое мы ему присвоим a.test = ‘test’- свойство test исчезнет с обёрткой).
    6. Узнали, что у объектов есть метод toString() который возвращает строковое представление объекта (для типа number valueOf() – вернёт числовое значение).
    7. Поняли, что при выполнении операций конкатенации или математических операциях примитивы могут переопределить свой тип в нужный. Для этого они используют функции-обёртки своих типов, но без оператора new (str = String(str)).(в чём разница и как это работает, поговорим дальше)
    8. И наконец, узнали, что typeof берёт значения из жёстко зафиксированной таблицы (вот откуда ещё одно заблуждение, основанное на typeof null //object).

    JavaScript или JS (сокращенно) не простой язык и начинающие разработчики узнают об этом не сразу. По началу они узнают азы и все кажется красочным и прекрасным. Заходя чуть глубже, появляются JavaScript массивы, объекты, callback’и и все подобное, что часто выносит мозг.

    В JavaScript важно правильно проверять тип переменной. Допустим вы хотите узнать является ли переменная массивом или объектом? Как это правильно проверить? В этом конкретном случае, есть хитрости во время проверки и именно о них будет эта запись. Давайте сразу приступим.

    Проверка типа переменной

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

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

    Var _comparison = { string: "строка", int: 99, float: 13.555, object: {hello: "привет"}, array: new Array(1, 2, 3) }; // Вернет массив с ключами объекта var _objKeys = Object.keys(_comparison); for(var i = 0; i <= _objKeys.length - 1; i++) { // выведем в консоль тип каждой переменной console.log(typeof _comparson[_objKeys[i]]); }

    Результат выполнения кода:

    String number number object object

    Верно? — Нет, конечно. Есть две проблемы. Каждая из них будет подробно описана и предложено решение.

    Первая проблема: float число, выводится как number

    Comparison.float не является числом и вместо number должно быть float (число с плавающей точкой).Чтобы это исправить, можно создать функцию с проверкой как в коде ниже.

    Var _floatNumber = 9.22; var _notFloatNumber = 9; console.log(isFloat(_floatNumber)); console.log(isFloat(_notFloatNumber)); console.log(isFloat("")); function isFloat(n){ return Number(n) === n && n % 1 !== 0; }

    Функция isFloat() выполняет проверку всех значений на числа с плавающей точкой. Сначала проверяется равна ли переменная n числу (Number(n) === n) и если да, то делается еще одна проверка на деление с остатком и если остаток есть, то возвращается булевой (true или false ) результат (n % 1 !== 0).

    В примере выше она возвращает true , false и false . Первое значение имеет float тип, второе нет — это обычное число и последнее всего лишь пустая строка, которая не подходит под правила.

    Вторая проблема: массив определился как объект

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

    Есть несколько способов для проверки переменной на тип массива.

    Первый вариант (хороший вариант). Проверяем принадлежность data к массиву с помощью instanceof ().

    Var data = new Array("hello", "world"); var isArr = data instanceof Array;

    Второй вариант (хороший вариант). Метод Array.isArray() возвращает булевое значение, которе будет зависеть от того является ли переменная массивом или нет ().

    Var data = new Array("hello", "world"); var isArr = Array.isArray(data);

    Третий вариант (самый лучший, но длинный). Для удобности, вы можете сделать этот способ функцией. Используя Object, мы делаем . Если результат Object.prototype.toString.call(data) не равен значит переменная не массив ().

    Var data = new Array("hello", "world"); var isArr = Object.prototype.toString.call(data) == ""; console.log(isArr);

    Последний результат в виде удобной функции:

    Function isArray(data) { return Object.prototype.toString.call(data) == "" }

    Теперь вы можете вызвать функции isArray() и как аргумент задать массив или что-то иное и посмотреть результат.

    Послесловие

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

    Если у вас остались какие-либо вопросы — пишите их ниже к этому записи. Я буду рад помочь.