CodeNix

692378482

codenix.sv

admin@codenix.net

Типи даних в JavaScript

Опубліковано: Категорія: JavaScript Переглядів: 2538

типи даних javascript

Типи даних в JavaScript можна розділити на дві категорії: прості (їх також називають примітивні або елементарні) типи і складні (об'єкти).

  • Прості
    • String - текстові рядки (зазвичай їх називають просто - рядки)
    • Number - числа
    • Boolean - логічні (булеві) значення
    • спеціальні значення
      • null
      • undefined
  • Складні
    • Object - звичайні об'єкти
    • Function - функції
    • Array - масиви

Спеціальні значення null і undefined є елементарними значеннями, але вони не відносяться ні до чисел, ні до рядків, ні до логічних значень. Кожне з них визначає тільки одне значення свого власного спеціального типу.

Будь-яке значення в мові JavaScript, яке не є числом, рядком, логічним значенням або спеціальним значенням null або undefined, є об'єктом. Об'єкт (тобто член об'єктного типу даних) являє собою колекцію властивостей, кожне з яких має ім'я і значення (або простого типу, такого як число або рядок, або об'єктного).

Звичайний об'єкт JavaScript являє собою невпорядковану колекцію іменованих значень. Крім того, в JavaScript є об'єкт спеціального типу, відомий як масив, що представляє упорядковану колекцію пронумерованих значень. Для роботи з масивами в мові JavaScript є спеціальні синтаксичні конструкції.

В JavaScript визначений ще один спеціальний тип об'єкта, відомий як функція. Функція - це об'єкт, з яким пов'язаний виконуваний код. Функція може викликатися для виконання певної операції і повертати розраховане значення. Подібно масивам, функції поводяться не так, як інші види об'єктів, і в JavaScript визначений спеціальний синтаксис для роботи з ними. Одна з найважливіших особливостей функцій в JavaScript полягає в тому, що вони є самими справжніми значеннями, і програми JavaScript можуть маніпулювати ними, як звичайними об'єктами.

Числа в JavaScript

Значеннями типу Number є цілі числа і числа з плаваючою крапкою. Для підтримки чисел різних типів передбачено кілька різних форматів числових літералів.

Для представлення чисел в JavaScript використовується 64-бітний формат, який визначається стандартом IEEE-754. Цей формат здатний представляти числа з плаваючою крапкою в діапазоні від 5e-324 до 1.7976931348623157e + 308. Найменше та найбільше числа, які можуть бути представлені в JavaScript, зберігаються у властивостях Number.MIN_VALUE і Number.MAX_VALUE.

Формат представлення чисел в JavaScript дозволяє точно представляти всі цілі числа в діапазоні від -9007199254740992 до 9007199254740992 включно. А значення з плаваючою точкою представляються з точністю до 17-го десяткового розряду (не включаючи сам 17 розряд). Через це наприклад, додавання 0.1 і 0.2 дає в результаті 0.30000000000000004 замість 0.3. Такі невеликі помилки округлення ускладнюють перевірку конкретних значень з плаваючою крапкою.

Дуже великі і дуже малі числа з плаваючою точкою можна представляти в експоненціальному записі. Експоненціальний запис означає число помножене на 10 у зазначеному степені. Число в експоненціальному записі складається з числа (цілого або з плаваючою точкою) за яким ставиться велика або мала літера E, після якої можна поставити необов'язковий знак плюс або мінус і далі показник степеня числа 10. Розглянемо наприклад значення 3.52x105 (352 000). Замість всього, що знаходиться між числом і експонентою, потрібно поставити букву "e", в результаті попередній запис можна представити у такому вигляді:

var bigNumber = 3.52e5;

За замовчуванням JavaScript переводить в експоненціальний запис будь-які значення з плаваючою точкою, що містять як мінімум шість нулів після крапки:

alert(0.0000005); // 5e-7

Будь-якому числовому літералу може передувати знак мінус (-), що робить число від'ємним.

Через те що для зберігання чисел з плаваючою точкою потрібно вдвічі більше пам'яті, ніж для цілих чисел, JavaScript по можливості перетворює їх в цілі числа. Якщо після десяткової точки немає розрядів, число стає цілим:

var num1 = 1.;  // Інтерпретується як ціле число 1
var num2 = 9.0  // Інтерпретується як ціле число 9

Числа можна вказувати також у вигляді шістнадцяткових або вісімкових значень. Шістнадцяткове значення починається з послідовності символів "0x" або "0X", за якою слідує саме значення. Букви шістнадцяткового числа можуть бути і малими, і великими:

alert(0Xff);  // Число 255
alert(0xFF);  // Число 255

У вісімковому літералі першою цифрою є нуль (0), за яким слідує послідовність вісімкових цифр (від 0 до 7). Якщо в літералі виявляється цифра не з цього діапазону, початковий нуль ігнорується і число інтерпретується як десяткове:

alert(070);  // 56
alert(079);  // 79

Спеціальні числові значення

В JavaScript існують глобальні змінні Infinity і NaN. Змінна Infinity зберігає спеціальне значення, що позначає нескінченність - Infinity, змінна NaN зберігає спеціальне значення NaN (NaN скорочення від англ. Not a Number - не числом). Ці змінні доступні тільки для читання.

Значення Infinity можна отримати:

  • В результаті ділення числа на 0.
  • Якщо результат арифметичної операції виявиться більше найбільшого або менше найменшого допустимого значення.
alert(123 / 0);     // Infinity
alert(-12345 / 0);  // -Infinity
alert(1e500);       // Infinity
alert(1 - 1e500);   // -Infinity

Якщо обчислення повертає одну з нескінченностей, це значення не може використовуватися ні в яких подальших обчисленнях, бо Infinity не має числового представлення.

Значення NaN використовується для позначення математичної помилки, вона виникає в тому випадку, якщо математична операція не може бути здійснена, наприклад:

var a = 10, b = "текст";
 
document.write(a - b);  // NaN
document.write(0 / 0);  // NaN

Значення NaN володіє однією особливістю: воно не дорівнює ніякому значенню, у тому числі й іншому NaN. Це означає, що не можна використовувати перевірку x == NaN, щоб визначити, чи є значення змінної x значенням NaN. Замість цього слід виконати перевірку x! = x. Ця перевірка поверне true тоді і тільки тоді, коли x має значення NaN. Аналогічну перевірку можна виконати за допомогою функції isNaN(). Вона повертає true, якщо аргумент має значення NaN або якщо аргумент є нечислове значенням (тільки таким, яке не може бути перетворено в число).

Крім цього, будь-яка арифметична операція з NaN (наприклад, NaN / 10) завжди повертає NaN.

Іноді в результаті арифметичної операції можна зустріти значення -0 (від'ємний нуль). Втрата значущих розрядів відбувається, коли результат арифметичної операції виявляється ближче до нуля, ніж мінімально можливе значення. У цьому випадку повертається число 0. Якщо втрата значущих розрядів відбувається в від'ємномурезультаті, повертається спеціальне значення -0. Це спеціальне значення нічим не відрізняється від звичайного нуля, за винятком тих випадків, коли воно виступає в ролі дільника.

alert(3 / 0);   // Infinity
alert(3 / -0);  // -Infinity

Помилки округлення дійсних чисел

Двійкове подання дійсних чисел нездатне забезпечити точне представлення таких простих чисел як 0.1. Двійкове подання дійсних чисел в JavaScript визначається відповідно до стандарту IEEE-754, в цьому стандарті приділено особливу увагу двійковій арифметиці чисел з плаваючою комою.

Точність подання дійсних чисел в JavaScript досить висока і дозволяє забезпечити дуже близьке представлення дійсного числа. Але той факт, що дійсне число може бути представлене точно, може призводити до проблем. Подивимося на наступний приклад:

var x = 0.3 - 0.2;
var y = 0.2 - 0.1;
 
document.write(x == y);    // false
document.write(x == 0.1);  // false
document.write(y == 0.1);  // true

Через помилки округлення різниця між числами 0,3 і 0,2 виявилася не рівною різниці між числами 0,2 і 0,1. Важливо розуміти, що ця проблема не є чимось характерним для JavaScript: вона проявляється у всіх мовах програмування, де використовується двійкове подання дійсних чисел. Варто звернути увагу, що значення x і y в прикладі вище дуже близькі один до одного і до істинного значення. Точність округлення цілком прийнятна для більшості застосувань: проблема виникає лише при спробах перевірити значення на рівність.

Рядки в JavaScript

Значеннями типу String є текстові рядки. В JavaScript рядок - це незмінна, упорядкована послідовність 16-бітних значень, кожне з яких представляє символ Unicode. Рядки можуть складатися з нуля і більше символів. Символи включають в себе букви, цифри, знаки пунктуації, спеціальні символи і пропуски. Рядки повинні бути поміщені в подвійні або одинарні лапки (апострофи):

var myColor = "red";
var myColor = 'red';

Рядки вкладені в подвійні лапки можуть містити символи одинарних лапок і навпаки.

Для того, щоб в рядку, укладеному в подвійні лапки, можна було використовувати подвійні лапки, потрібно їх екранувати за допомогою зворотного слеша (\), теж саме стосується і рядка вкладеного в одинарні лапки:

document.write("використовуються \"подвійні\" лапки");
document.write('використовуються \'одинарні\' лапки');

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

Для представлення символів Unicode в JavaScript використовується кодування UTF-16. Більшість найбільш часто використовуваних символів Unicode мають кодові пункти, що вміщаються в 16 біт, і можуть бути представлені єдиним елементом рядка. Символи, кодові пункти яких не вміщаються в 16 біт, кодуються відповідно до правил кодування UTF-16 як послідовності з двох 16-бітних значень. Це означає, що рядок, що має довжину, рівну 2 (два 16-бітних значення), може представляти єдиний символ:

var p = "π";  // складається з одного 16-бітного значення
var e = "

Логічні (булеві) значення

Тип Boolean має тільки два допустимих значення. Ці два значення є ключовими словами true (істина) і false (неправда). Логічне значення говорить про істинність або хибність чогось. Присвоїти логічні значення змінним можна наступним чином:

var found = true;
var lost = false;

Зазвичай булеві значення являють собою результат операцій порівняння, виконуваних в сценарії, наприклад:

x == 7

Цей вираз перевіряє, чи рівне значення змінної x числу 7. Якщо так, результатом цього порівняння буде логічне значення true. Якщо значення змінної x не дорівнює 7, результатом порівняння буде - false.

Булеві значення зазвичай використовуються в керуючих конструкціях. Наприклад, інструкція if/else виконує одну дію, якщо булево значення дорівнює true, і іншу дію, якщо false.

Булеві значення виходять не тільки в результатах порівняння - будь-яке значення в JavaScript може бути перетворено в булево значення. Наступні значення в результаті перетворення дають значення false:

  • undefined
  • null
  • 0
  • -0
  • NaN
  • "" - пустий рядок

Всі інші значення при перетворенні дають в результаті значення true. Значення false і шість значень, які при перетворенні приводяться до цього значення, зазвичай називають помилковими значеннями, а всі інші - істинними. У будь-якому контексті, коли інтерпретатор JavaScript очікує отримати логічне значення, помилкові значення інтерпретуються як false, а істинні значення - як true.

Null і Undefined в JavaScript

Тип Null має всього одне значення - null. Значення null є спеціальним порожнім об'єктом. Ключове слово null в JavaScript має спеціальне призначення - воно використовується для позначення відсутності очікуваного значення. Наприклад воно використовується для ініціалізації змінної, якій згодом буде присвоєно об'єкт.

if (car != null) {
}

Тип Undefined має всього одне значення - undefined. Значення undefined вказує на початкову відсутність будь-якого значення. Отримати значення undefined можна наступним чином:

  • При зверненні до змінної, яка була оголошена, але не була ініціалізована.
  • При зверненні до неіснуючої властивості об'єкта.
  • При зверненні до неіснуючого елементу масиву.
  • При зверненні до параметрів функції, яким не були передані аргументи при виклику функції.
  • Повертається функціями, які не мають значення, що повертається.
  • Повертається оператором typeof при перевірці типу неіснуючої змінної.
var bar;
document.write(bar);

Ідентифікатор undefined є ім'ям визначеної глобальної змінної (а не ключовим словом, як null), яка ініціалізована значенням undefined. Змінна undefined доступна тільки для читання.

Ні null, ні undefined не мають будь-яких властивостей або методів. Спроба використати . або [], щоб звернутися до властивості або методу цих значень, викликає помилку TypeError, яку можна побачити в консолі браузера.

При порівнянні значень null і undefined, оператор рівності (==) вважає їх рівними, а оператор суворої рівності (===) - різними.

На практиці, значення undefined можна розглядати як ознаку несподіваного або помилкової відсутності якого-небудь значення, а null - як ознаку звичайної або цілком очікуваної відсутності значення.

Присвоєння за значенням і за посиланням

Примітивні типи завжди присвоюються за значенням. Коли ви присвоюєте примітивне значення змінної (властивості або елементу масиву), значення копіюється в цю змінну. Змінна, що містить примітивне значення, містить безпосередньо саме значення, а не посилання на нього. Це означає, що, якщо одній зміній привласнити значення іншої змінної, кожна змінна буде мати власну копію значення:

var color1 = "red";
var color2 = color1;

Тут змінній color1 присвоюється значення "red". Потім змінній color2 присвоюється значення змінної color1. Незважаючи на те, що змінні color1 і color2 мають однакове значення, кожна з них містить власну копію значення, тому зміна значення однієї з них не вплине на іншу.

var color1 = "red";
var color2 = color1;
 
document.write(color1);          // "red"
document.write("<br>" + color2); // "red"
 
color1 = "blue";
 
document.write("<br>" + color1); // "blue"
document.write("<br>" + color2); // "red"

Посилальні типи присвоюються за посиланням, а не за значенням. Операція присвоювання об'єкта (також масиву або функції) фактично присвоює посилання, тобто вона не створює нову копію об'єкта, а привласнює посилання на вже існуючий об'єкт:

var obj1 = {};
var obj2 = obj1;  // Теперь посилається на той  же об'єкт в пам'яті, що і obj1

Так як дві змінні містять посилання на один і той самий об'єкт, зміни об'єкта зроблені в одній з змінних вплинуть на іншу.

Якщо в програмі потрібно створити копію об'єкта, необхідно буде явно скопіювати властивості і методи від одного об'єкта іншому.

Також, якщо буде потрібно порівнювати два окремих об'єкта, необхідно буде порівнювати їх властивості та методи.

Об'єкти обгортки

В JavaScript є визначений набір властивостей і методів для роботи з рядками, числами і логічними значеннями, вони використовуються точно так, як властивості і методи в роботі з звичайними об'єктами. Це реалізовано для того, щоб з примітивними значеннями було також легко працювати, як і зі звичайними об'єктами, наприклад, якщо нам потрібно перетворити всі символи рядка в нижній регістр ми скористаємося методом toLowerCase().

Однак в JavaScript примітивні значення не є об'єктами, так чому ж вони володіють властивостями і методами? Всякий раз, коли в програмі робиться спроба звернутися до властивості або методу примітивного значення, інтерпретатор JavaScript на час перетворює примітивне значення в об'єкт. Цей об'єкт використовується інтерпретатором для доступу до потрібної властивості або методу. Після звернення до методу або властивості новостворений об'єкт знищується. Тимчасові об'єкти, які створюються при зверненні до властивості або методу рядка, числа або логічного значення, називаються "об'єкти обгортки".

Об'єкти обгортки створюються тільки для значень, які відносяться до типів String, Number і Boolean. Значення null і undefined не мають об'єктів обгорток: будь-яка спроба звернутися до властивостей цих значень буде викликати помилку TypeError.

var str = 'машина';
alert(str.charAt(0));

Нижче показана приблизна реалізація того, що робить інтерпретатор JavaScript в момент звернення до методу charAt():

temp = new String(str);       // Створюється тимчасовий об'єкт
alert(temp.charAt(0));        // Виклик потрібног методу
delete temp;                  // Видалення тимчасового об'єкту

Як ми бачимо, інтерпретатор JavaScript автоматично створює об'єкт типу String, у якого він потім викликає метод charAt(). Створений об'єкт використовується всього один раз перед тим як буде знищений складальником сміття.

Якщо спробувати встановити значення властивості, ця спроба буде просто проігнорована: зміна торкнеться тимчасового об'єкту тільки в момент його створення і не буде збережено, оскільки відразу після цього знищується:

var str = "fdsf";
alert(str.len);  // undefined, так як така властивість відсутня
 
str.len = 5;     // встановлює властивість зі значенням. Відразу після цього об'єкт знищується
alert(str.len);  // undefined, так як об'єкт вже був знищений і такої властивості немає

Об'єкти обгортки можна розглядати просто як особливість реалізації в JavaScript і взагалі не думати про них.

Змінювані і незмінні типи

Між простими типами і посилальними в мові JavaScript є фундаментальні відмінності. Прості значення є незмінними, тобто просте значення неможливо змінити. Наприклад, всі рядкові методи, які, на перший погляд повертають змінений рядок, насправді повертають нове строкове значення:

var str = "привіт";
document.write(str.toUpperCase()); // повертає "ПРИВІТ", але значення str не змінилось
document.write(str); // повертає "привіт"

Посилальні значення (тобто об'єкти, масиви і функції) відрізняються від простих, вони є змінюваними значеннями, тобто їх можна змінювати:

var o = { x: 1 }; // Початкове значення об'єкта
o.x = 2;          // Змінюємо об'єкт, змінивши значення властивості
o.y = 3;          // Змінюємо об'єкт, добавивши нову властивість

Коментарі