Навчальні матеріали з автоматизації технологічних процесів та виробництв, розроблені спільнотою
JavaScript (скорочено JS ) — мова програмування, яка використовується для сценаріїв (скриптів). Рушій JavaScript підключається до об’єктів свого середовища виконання (наприклад, веб-браузера) та надає можливість керування ними.
JS це реалізація стандарту ECMAScript. ES - це скорочення від ECMAScript. Кожне видання специфікації отримує назву з абревіатурою ES та номеру версії. Починаючи з ES6 офіційна назва специфікації позначається роком виходу. Тобто ES2015…ES2019…
Не дивлячись на схожість назв і елементів синтаксису, JavaScript та Java - це різні мови, які навіть відрізняються парадигмами програмування. Серед відмінностей окремо виділимо середовища виконання.
Java компілюється в проміжний байт-код, який на необхідному для виконання середовищі перетворюється на машинний код та виконується за допомогою Java-машини. Таким чином, реалізовуючи Java-машину (JVM) на різному залізі т ОС реалізовується крос-платформність.
рис.2.1. Принципи роботи Java для порівняння з Java Script
На відміну від системи з проміжною компіляцією, мова JavaScript - інтерпретована. Тобто аналізується та виконується вихідний код програми JavaScript-рушієм. Цей рушій може бути вбудований наприклад в браузер.
Таким чином, JavaScript найчастіше використовується як частина браузера, що надає можливість виконання коду на стороні клієнта (на пристрої кінцевого користувача), взаємодіяти з ним, керувати браузером, обмінюватися даними з сервером, змінювати структуру та зовнішній вигляд веб-сторінки. Однак рушій може бути частиною іншого застосунку або бути окремим застосунком, наприклад серверним.
рис.2.2. Принципи роботи Java Script
Таким чином, JavaScript використовується для:
Серед рушіїв можна виділити:
Якщо спрощено, рушії працюють за таким алгоритмом: читають та розбирають (парсять) текст скрипта; перетворюють скрипт в машинний код; запускають машинний код. При цьому можуть використовуватися алгоритми оптимізації.
У даному курсі будуть використовуватися приклади в основному для серверних застосунків, що виконуються на Node.js
Для створення скриптів та застосунків можна використовувати різні редактори, IDE (інтегровані середовища розробки, Integrated Development Environment) або/та утиліти розробки. При розробці скриптів для Веб-сторінок можна скористатися інтегрованими у Веб-бразуери утилітами. Наприклад для FireFox є Веб-консоль, яка може працювати у мультирядковому режимі. Можна вводити туди JS код і дивитися результат, запустивши його на виконання.
рис.2.3. Налагоджувач JS в консолі WEB-браузера FireFox
У останніх версіях, при намаганні скопіювати в консоль текст, FireFox попросить один раз явно написати дозвіл на виконання копіпасту. Слід також розуміти, що код в консолі буде запускатися в контексті відкритої сторінки.
У Google Chrome можливість перевірки коду доступна в Інструментах розробника. Введені у консолі інструкції одразу виконуються після натискання Enter
. Якщо необхідно ввести кілька рядків інструкцій, після кожної треба вводити Shift+Enter
.
рис.2.4. Налагоджувач JS в консолі WEB-браузера Google Chrome
У даному курсі усі приклади для лабораторних робіт наводяться для безкоштовного IDE середовища Visual Studio Code. Код пишеться в файлах *.js
, які можна об’єднати в один проект, наприклад для серверу Node.js
.
рис.2.5. Інструментальне середовище Visual Studo Code
Таким чином, усі приклади, що наведені нижче, можете тестувати у Visual Studio Code: створити файл, зберегти його як test.js
, копіювати туди код і запускати на виконання F5
.
Код складається з набору інструкцій, які розділені символом ;
. У наступному фрагменті дві інструкції введені через крапку з комою в одному рядку.
console.log("Привіт світ!"); console.log("Друга інструкція.");
У наведених вище інструкціях викликається метод log
вбудованого системного об’єкту console
. Це дає можливість виводити на налагоджувальну консоль текстові повідомлення.
Мова JavaScript чутлива до регістру. Наприклад код console.Log()
видасть помилку, так як у системному об’єкті console
методу Log
не існує, натомість є метод log
.
Синтаксис коментарів такий самий, як в C
та багатьох інших мовах програмування:
console.log("Привіт світ!"); // коментар для одного рядка
/* довгий коментар
на кілька рядків
*/
/* Однак, не можна /* змішувати коментарі */ тут буде SyntaxError */
При необхідності виконувати кілька інструкцій при керуванні потоком виконання (наприклад, if
, for
, while
), використовують блокові інструкції {
та }
. Все що знаходиться в межах фігурних дужок об’єднується в одну інструкцію.
let a=3; let b=2;
if (a>b) //якщо треба виконати кілька інструкцій коли a>b
{ //початок блоку
console.log("Це перша інструкція блоку.");
console.log("Це друга інструкція блоку.");
} //кінець блоку
Для створення змінної в JavaScript використовуються ключові слова let
та var
. Оператор let
оголошує локальну змінну, яка видима в межах блоку, де вона оголошена ({}
). Оператор var
має область видимості у межах усіє функції. Є ще ряд відмінностей між let
та var
, але тут вони не розглядаються. У нових скриптах рекомендується використовувати let
.
Наведений нижче приклад створює (іншими словами: об’являє або означує) змінну з іменем message
, і поміщає в неї дані, використовуючи оператор присвоювання =
. Рядок збережеться в області пам’яті, зв’язаною зі змінною. Ми можемо отримати до неї доступ, використовуючи ім’я змінної.
let message1;
message1 = 'Hello'; // записати рядок в змінну
console.log(message1); // пише в консоль значення змінної
let message2 = 'Hello';//Можна суміщати об'явлення змінної і запис даних в один рядок.
let user = 'John', age = 25, message3 = 'Hello';//можна кілька змінних об'являти в одному рядку
//або навіть так
let user1 = 'John',
age1 = 25,
message4 = 'Hello';
Оголошення const
створює посилання на значення, доступне лише для читання. Що не гарантує незмінність значення, на котре вказує посилання, а лише той факт, що не можна повторно присвоїти будь-яке значення змінній з відповідним ім’ям.
Коли ви оголошуєте змінну за межами будь-якої функції, вона називається глобальною змінною, оскільки вона доступна для будь-якого іншого коду в поточному документі. Коли ви оголошуєте змінну в межах функції, вона називається локальною змінною, оскільки доступна лише в межах цієї функції.
Змінна в JavaScript може містити будь-які дані. У один момент там може бути текст, а в інший – число. Тобто під час виконання програми тип може змінюватися кілька раз (так звана “динамічна типізація”). У наведеному нижче коді, одній змінній присвоюють різні за типом значення. Оператор typeof
повертає значення типу.
//в JS тип може змінюватися під час виконання програми
let message = "hello"; //це текст, і message тепер типу string
console.log (typeof(message));//string
message = 123456; //це число, і message тепер типу number
console.log (typeof(message));//number
У JavaScript існує сім типів даних: number
, string
, boolean
, null
, undefined
, object
, symbol
. Спочатку розглянемо базові (примітивні) типи, усі інші типи будуть розглянуті пізніше. Детальніший розгляд типів можна подивитися у розділі “Типи даних та літерали” з довідника.
У JavaScript примітивні типи даних number
, string
, boolean
, подібно об’єктам мають методи і властивості, до яких можна звертатися через крапку. Для цього JavaScript при такому доступі створює спеціальний об’єкт-обгортку, який надає потрібну функційність, після чого видаляється. Ці об’єкти мають відповідні назви String
, Number
, Boolean
і Symbol
, і мають різний набір методів. Наприклад, у наведеному нижче фрагменті, метод toUpperCase
з об’єкту типуString
виводить рядок зі зміненим регістром літер на усі великі.
let message = "привіт";
console.log (message);//привіт
console.log (message.toUpperCase());//ПРИВІТ
Особливими типами є null
та undefined
. Тип і значення null
значить буквально нічого
. Значення undefined
значить, що змінна є, але їй не було присвоєне значення.
let x;
console.log(x); // виведе "undefined"
Булевий тип (boolean
) може приймати значення: true
(істина) і false
(хибність). Можна записати у таку змінну результат операції порівняння або логічної операції.
let isGreater = 4 > 1;
console.log(isGreater); // буде true
let a = true; // використання булевого літералу "true"
До булевих значень можна застосовувати логічні оператори “І” (&&
), “АБО”(||
), “НЕ”(!
). Однак, оператори &&
та ||
насправді повертають значення одного з заданих операндів. Тому, якщо ці оператори використовуються зі значеннями не булевого типу, вони повернуть значення того самого типу. Оскільки логічні вирази обчислюються зліва направо, вони перевіряються на можливе “коротке замикання”, тобто обчислення проходить за наступними правилами:
false
&&
будь-що
дає результат false
.true
||
будь-що
дає результат true
.Правила логіки гарантують, що ці обчислення завжди будуть правильними. Зауважте, що частина виразу будь-що
не обчислюється, тому будь-які побічні ефекти від цих обчислень не відбудуться.
let a1 = true && true; // t && t вертає true
let a2 = true && false; // t && f вертає false
let a3 = false && true; // f && t вертає false
let a4 = false && (3 == 4); // f && f вертає false
let a5 = 'Кіт' && 'Пес'; // t && t вертає Пес
let a6 = false && 'Кіт'; // f && t вертає false
let a7 = 'Кіт' && false; // t && f вертає false
let o1 = true || true; // t || t вертає true
let o2 = false || true; // f || t вертає true
let o3 = true || false; // t || f вертає true
let o4 = false || (3 == 4); // f || f вертає false
let o5 = 'Кіт' || 'Пес'; // t || t вертає Кіт
let o6 = false || 'Кіт'; // f || t вертає Кіт
let o7 = 'Кіт' || false; // t || f вертає Кіт
let n1 = !true; // !t вертає false
let n2 = !false; // !f вертає true
let n3 = !'Кіт'; // !t вертає false
У JavaScript усі числові дані, як цілочисельні значення, так і числа з плаваючою комою представлені через тип даних (number
). Для дуже великих цілих чисел (більше за модулем, ніж два в степені 53), застосовується спеціальний об’єкт - BigInt
, у цій лекції не будемо його розглядати.
У якості літералів, крім звичайних чисел (15
чи 36.6
) існують спеціальні числові значення: Infinity
(нескінченність), -Infinity
(мінус нескінченність) і NaN
(не число).
console.log(1+2);//видасть 3
console.log(1.1+2.1);//видасть 3.2
console.log("2"+3);//видасть "23"
console.log("два"+3);//видасть "два3"
console.log(2/"0.5");//видасть 4
console.log("два"/3);//видасть NaN
console.log(1/0);//видасть Infinity
Цілочисельні літерали типу number
можна виразити у різних формах. Це задається першою літерою літералу:
0o
- вісімкової ,0x
- 16-кової,0b
- для 2-кової.console.log(-345); //-345
console.log(-0o77); //-63
console.log(-0xF1A7); //-61863
console.log(-0b11); //-3
Літерали з плаваючою комою можуть задаватися у різному форматі:
console.log(3.1415926); //3.1415926
console.log(-.123456789);//-0.123456789
console.log(-3.1E+12); //-3100000000000
console.log(.1e-3); //0.0001
Як наводилося вище, примітивні типи можуть використовуватися як об’єкти. Об’єкт-обгортка Number
має багато корисних властивостей та методів. Наприклад метод toString
виводить значення типу String
у вказаній у дужках системі числення.
let a=0xF; //16-ковий формат
console.log (a.toString(2)); // 1111 - двійковий формат
Про об’єктні властивості та методи Number
можна прочитати у наступній лекції.
string
Рядок (string
) в JavaScript повинна бути взята в лапки.
let str = "Рядок в подвійних лапках";
let str2 = 'Можна використовувати одинарні лапки';
let phrase = `Зворотні лапки (зліва від '1') дозволяють вставляти значення змінних ${str}, інші лапки таке не дозвоялють робити`;
Крім звичайних символів до рядків можна також включати спеціальні, як це показано в наступному прикладі. Весь перелік символів доступний у розділі string з довідника.
console.log ("один рядок \n інший рядок"); //виведеться в два рядки
Об’єкт-обгортка String
мають багато корисних методів і властивостей. Повний перелік наведений у довіднику. У прикладі нижче, деякі з них:
let a='Текст';
console.log (a.length); //5 - довжина, тобто кільксть літер
console.log (a.toLowerCase());//текст - усі літери маленькі
console.log (a[2]); //к - доступ до літери по номеру
for (let char of a='Текст') {//перебір усіх символів
console.log(char); // Т,е,к,с,т
}
console.log(a.substring(0,3)); //Тек - підрядок з 0-го по 3-й не включно
console.log(a.substr(1,2)); //ек - підрядок з 1-го, 2 шт
Додатково про роботу зі змінними string
та виразами можна почитати за цим посиланням або за цим.
Оператор typeof
повертає тип аргумента. Він працює однаково з довма синтаксисами
typeof операнд
typeof (операнд)
console.log (typeof undefined);// "undefined"
console.log (typeof 0) ;// "number"
console.log (typeof true); // "boolean"
console.log (typeof "foo"); // "string"
console.log (typeof Symbol("id")); // "symbol"
conso;e.log (typeof (['Я','М']));//"object", бо масиви це об'єкти
console.log (typeof Math); // "object" - так як Math вбудований в JS обєкт для роботи з мат.операціями
console.log (typeof null); // "object" - хоч це не так
console.log (typeof console.log); // "function" - хоч формально такого типу немає, для методів і функцій повертається "function"
Найчастіше оператори і функції автоматично перетворюють передані їм значення (примітивного типу) до потрібного типу. Наприклад, console.log
автоматично перетворює будь-яке значення до типу string
. Математичні оператори перетворюють значення до чисел. Але є випадки, коли потрібно явно перетворити значення в очікуваний тип.
Можна використовувати функцію String (value)
, щоб явно перетворити значення до рядка:
let value = true;
console.log (typeof value); // boolean
value = String(value); // тепер це рядок, що дорівнює "true"
console.log (typeof value); // string
Можна використати функцію Number(value)
, щоб явно перетворити value
в число. Якщо рядок не може бути перетворений в число, результатом буде NaN
.
let str = "123"; console.log(typeof str); // string
let num = Number(str); console.log(typeof num); // стає числом 123, тому number
let age = Number("Будь який рядок без числа"); console.log(age); // NaN, перетворення не вдалося
console.log(Number(" 123 ") ); // 123
console.log(Number("123z") ); // NaN (помилка читання числа в "z")
console.log(Number(true) ); // 1
console.log(Number(false) ); // 0
Майже усі математичні оператори виконують чисельне перетворення, за виключенням +
. Якщо один із доданків є рядком, тоді всі інші приводяться до строчок і робиться конкатенація (з’єднання).
console.log("1.1" + "1.1"); //"1.11.1"
console.log((+"1.1") + (+"1.1"));//2.2
У випадку, коли значення, що представляє число, знаходиться в пам’яті як рядок, існують методи для перетворення parseInt()
та parseFloat()
.
console.log(Boolean(1)); // true
console.log(Boolean(0)); // false
console.log(Boolean("Привіт!")); // true
console.log(Boolean("")); // false
console.log(Boolean("0")); // true
console.log(Boolean(" ")); // пробіл це також true (любий непустий рядок це true)
Лівосторонньому операнду =
дається значення правостороннього виразу.
let x = 2 * 2 + 1;
console.log(x); // 5
let a, b, c;
a = b = c = 2 + 2; //присвоєння ланцюжком, усім змінним буде присвоєно 4
let a1 = 1; //1
let b1 = 2; //2
let c1 = 3 - (a1 = b1 + 1);//0
Оператор порівняння порівнює операнди та повертає логічне значення істинності порівняння. Операнди можуть бути числовими, рядками, логічними значеннями або об’єктами. Рядки порівнюються згідно стандартного лексикографічного порядку, з використанням значень Unicode.
У більшості випадків, якщо два операнди не належать до одного типу, JavaScript намагається привести їх до належного для порівняння типу. Зазвичай це призводить до числового порівняння операндів. Єдиними винятками у конвертації типів під час порівняння є оператори ===
та !==
, які виконують перевірку на строгу рівність та строгу нерівність. Ці оператори не намагаються перед перевіркою на рівність привести операнди до спільного типу.
Наступний приклад показує як працюють оператори. Усі виведення в консоль будуть давати результат TRUE.
let var1 = 3; let var2 = 4;
//усі наведені нижче приклади виведуть значення TRUE;
console.log (3 == var1); //рівність
console.log ("3" == var1); //рівність
console.log ("3" == 3); //рівність
console.log (var1 != 4); //нерівність
console.log (var2 != "3"); //нерівність
console.log (3 === var1); //строга рівність, оператори рівні і одного типу
console.log (var1 !== "3"); //строга нерівність, оператори одного типу, але нерівні
console.log (3 !== '3'); //строга нерівність, оператори різного типу
console.log (var2 > var1); //більше ніж
console.log ("12" > 2); //більше ніж
console.log (var2 >= var1); //більше абл дорівнює
console.log (var1 < var2); //менше ніж
console.log (var1 <= var2); //менше або дорівнює
Арифметичний оператор приймає числові значення (літерали чи змінні) в якості операндів та повертає єдине числове значення. Стандартними арифметичними операторами є додавання (+
), віднімання (-
), множення (*
) та ділення (/
). Ці оператори працюють так само, як і в більшості інших мов програмування, при використанні з числами з рухомою комою (зокрема, зауважте, що ділення на нуль повертає Infinity
). Робота з іншими арифметичними операторами показана у прикладі нижче:
let x=3;
console.log (12 % 5); //2, остача від ділення
console.log (++x); console.log (x); //4(інкрменет, потім вивід), потім 4
console.log (x++); console.log (x); //4(вивід потім інкремент), потім 5
console.log (--x); console.log (x); //4(декрменет, потім вивід), потім 4
console.log (x--); console.log (x); //4(вивід потім декремент), потім 3
console.log (-x); //-3, унарний мінус робить знак протилежним
console.log (+"3"); //-3, унарний плюс перетворює операнд на число
console.log (2**3); //8, підносить до степеня
Бітовий оператор опрацьовує свої операнди, як послідовність 32-х бітів (нулів та одиниць). Бітові оператори виконують операції над цими бітовими представленнями і повертають стандартні числові значення JavaScript. Кожен біт першого операнду ставиться у пару до відповідного біту другого операнду: перший до першого, другий до другого, і так далі. Наступний приклад показує результати таких операцій.
let a;
a = 0b1101 & 0b1000; console.log (a.toString(2));//1000, побітове І
a = 0b1101 | 0b1010; console.log (a.toString(2));//1111, побітове АБО
a = 0b1101 ^ 0b0001; console.log (a.toString(2));//1100, побітове виключне АБО, повертає 0 там де біти однакові
a = ~ 0xFFFF_FFF0; console.log (a.toString(2));//1111, інвертує біти
//при зсуві усі біти на краю куди зсовують "випадають", а звідки - заповнюються нулями
a = 0b0011 << 3; console.log (a.toString(2));//11000, зсуває на три біти ліворуч
a = 0b11100 >> 4; console.log (a.toString(2));//1, зсуває на 4 біти праворуч,
a = 0x8000_0000 >> 16; console.log (a.toString(16));//-8000, зсуває на 16 біт праворуч, але знак залишає
a = 0x8000_0000 >>> 16; console.log (a.toString(16));//8000, зсуває на 16 біт праворуч, знак приймає як біт
На додачу до операторів порівняння, які можуть застосовуватись до рядкових значень, оператор конкатенації (+) об’єднує значення двох рядків, повертаючи єдиний рядок. Наприклад,
console.log('мій ' + 'рядок'); // консоль виводить рядок "мій рядок".
Для конкатенації рядків може також застосовуватись скорочений оператор присвоєння += . Наприклад,
let mystring = 'алфа';
console.log (mystring += 'віт'); // повертає "алфавіт" та присвоює це значення mystring.
Умовний оператор - єдиний оператор у JavaScript, який приймає три операнди. У оператора може бути одне чи два значення, в залежності від умови. Використовує наступний синтаксис:
умова ? значення1 : значення2
Якщо умова
дорівнює true
, оператор повертає значення1
. В іншому випадку - значення2
. Умовний оператор можна використовувати будь-де, де використовується звичайний оператор. Наприклад:
let age = 19;
let status = (age >= 18) ? 'дорослий' : 'неповнолітній';
console.log (status); //дорослий
Ця інструкція присвоює значення “дорослий” змінній status
, якщо значення age
(вік) більше чи дорівнює 18. Інакше, вона присвоює змінній status
значення “неповнолітній”.
Оператор кома (,
) обчислює обидва свої операнди та повертає значення останнього операнду. Цей оператор найчастіше використовується всередині циклу for
, що дозволяє оновлювати більше однієї змінної на кожному проході циклу. Наприклад, якщо a
є двовимірним масивом з 10 елементами по кожній стороні, наступний код використовує оператор кому, щоб оновити дві змінні одночасно. Код виводить значення діагональних елементів масиву:
for (var i = 0, j = 9; i <= j; i++, j--)
console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
Як і в інших мовах if, дозволяє робити галуження.
let a=3; let b=2;
if (a>b) {
console.log ("a>b");
} else {
console.log ("a<=b");
}
//використання else if
if (a>b) {
console.log ("a>b");
} else if (a<b) {
console.log ("a<=b");
} else {
console.log ("a=b");
}
Конструкція switch
замінює собою одразу кілька if
. Вона має один або кілька блоків case
і необов’язковий блок default
.
switch(x) {
case 'value1': // if (x === 'value1')
...
[break]
case 'value2': // if (x === 'value2')
...
[break]
default: //якщо не знайдено жодного варіанту
...
[break]
}
Приклад використання switch
:
let a = 2 + 2;
switch (a) {
case 3:
console.log( 'Малувато' );
break;
case 4:
console.log( 'В точку!' ); //виведе цей варіант
break; //після чого перестане перебирати
case 5:
console.log( 'Перебор' );
break;
default:
console.log( "Нема таких значень" );
}
Якщо break
немає, то виконання піде нижче по наступнимcase
, при цьому інші умови ігноруються.
let a = 2 + 2;
switch (a) {
case 3:
console.log( 'Малувато' );
case 4:
console.log( 'В точку!' ); //виконається, бо a = 4
case 5:
console.log( 'Перебор' ); //виконається, бо немає `break`
default:
console.log( "Нема таких значень" );//виконається, бо немає `break`
}
Можна групувати кілька варіантів, тобто у наступному прикладі будь який з пунктів 3
або 5
приведе до виконання console.log('Трохи не попали!')
.
let a = 3;
switch (a) {
case 4:
console.log('Правильно!');
break;
case 3: // (*) групуємо оба case
case 5:
console.log('Трохи не попали!');
break;
}
Код з тіла циклу while виконується, поки умова виконується. Наприклад, цикл нижче виводить i
, поки i < 3
let i = 0;
while (i < 3) { // виводить 0, потім 1, потім 2
console.log( i );
i++;
}
Одне виконання циклу називається ітерацією. Вище наведено 3 ітерації. Якщо тіло циклу має тільки одну інструкцію, оператори блоку {…}
можна не писати
let i = 3;
while (i) console.log(i--);
Синтаксис do..while дає можливість виконати тіло циклу принаймні один раз.
do {
// тіло циклу
} while (condition);
“Класичний” цикл for має наступний вигляд:
for (початок; умова; крок) {
// ... тіло циклу ...
}
Цикл нижче виконує console.log(i)
для i
від 0
до (але не включаючи) 3
:
for (let i = 0; i < 3; i++) { // виведе 0, потім 1, потім 2
console.log(i);
}
частина | ||
---|---|---|
початок | i = 0 |
Виконується один раз при вході в цикл |
умова | i < 3 |
Перевіряється перед кожною ітерацією циклу. Якщо вона буде false - цикл зупиниться. |
крок | i++ |
Виконується після тіла циклу на кожній ітерації перед перевіркою умови. |
тіло | console.log(i) |
Виконується знову і знову, поки умова виконується true . |
Можна використовувати існуючу змінну. Будь яка частина for
може бути пропущена.
Інші інструкції циклів будуть розглянуті в розділі Масиви
Можна вийти з циклу у будь який момент за допомогою директиви break. Наприклад:
let sum = 0;
while (true) {
let value = +prompt("Введіть число", '');
if (!value) break; // (*)
sum += value;
}
alert( 'Сумма: ' + sum );
Директива continue забезпечує перехід до наступної ітерації:
for (let i = 0; i < 10; i++) {
// якщо парне, пропустити іншу частину тіла циклу
if (i % 2 == 0) continue;
console.log(i); // 1, потім 3, 5, 7, 9
}
Окрім вбудованих системних функцій є також можливість писати власні. Тут наведемо тільки базові можливості функцій, інші будуть даватися в одній із наступних лекцій.
Оголошення функції (функціональний оператор) означує функцію з вказаними параметрами.
function name([param[, param,[..., param]]]) {
[statements]
}
name
- Ім’я функції.param
- Ім’я аргументу, що передається у функцію.statements
- Інструкції, які складають тіло функції.Функції повинні бути в області видимості під час виклику, але оголошення функції може бути записаним нижче виклику, як у цьому прикладі:
console.log (sum(2)); //значення параметра b не задається, результат виведе 5
function sum(a, b=3) { //b з передачою значення за замовченням
return (a+b);
}
У функцію можуть передаватися параметри за замовченням, як показано вище в прикладі для змінної b.
Примітивні параметри (такі, як число) передаються функціям за значенням, тобто якщо функція змінює значення параметра, ця зміна не відбувається в змінній, яка була передана при виклику.
let a=2;
console.log (test(a)); //3
console.log (a); //2
function test(a) {
a=3;
return (a);
}
Об’єкти передаються функції за посиланням. А отже функція може змінити цей об’єкт.
let a={val:2};
console.log (test(a)); //3
console.log (a.val); //3
function test(a) {
a.val=3;
return (a.val);
}
Функції також можуть бути створені за допомогою функціональних виразів, які можна присвоювати змінним. Така функція може бути анонімною, тобто їй не обов’язково мати ім’я. Наприклад, square
можна визначити як:
let square = function(number) { return number * number; };
let x = square(4); // повертає 16
Тим не менше, ім’я може бути надане у функціональному виразі, і може бути використане всередині функції, щоб звернутися до самої себе, або в налагоджувачі, щоб визначити функцію в трасуванні стеку:
var factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1); };
console.log(factorial(3));
Підняття функції (використання раніше об’явлення) працює тільки для оголошення функції, а не для функціонального виразу.
Функціональні вирази зручні при передачі функції як аргументу до іншої функції. Наступний приклад показує функцію map, яка повинна отримати функцію як перший аргумент, а масив як другий аргумент.
function map(f, a) {
let result = [], // Створення нового масиву
i;
for (i = 0; i != a.length; i++)
result[i] = f(a[i]);
return result;
}
Змінні, означені всередині функції, недоступні ззовні цієї функції. Проте, функція може звертатись до усіх змінних та функцій, означених у області видимості, де вона оголошена. Іншими словами, функція, оголошена у глобальній області видимості, може звертатись до усіх змінних, оголошених у глобальній області видимості. Функція, оголошена всередині іншої функції, має доступ до усіх змінних, оголошених у батьківській функції, а також до будь-якої змінної, до якої має доступ батьківська функція.
// Ці змінні визначені у глобальній області видимості
let num1 = 20, num2 = 3, name = 'Chamahk';
// Ця функція означена у глобальній області видимості
function multiply() {
return num1 * num2;
}
console.log (multiply()); // Повертає 60
// Приклад вкладеної функції
function getScore() {
let num1 = 2, num2 = 3;
function add() {
// використовуються змінні об'явлені в функції getScore
return name + ' scored ' + (num1 + num2);
}
return add();
}
console.log (getScore()); // Повертає "Chamahk scored 5"
object
- у JavaScript це колекція властивостей і методів. Методом називається функція, яка є членом об’єкта. Властивість це значення або набір значень (у вигляді масиву або об’єкта), який є членом об’єкта і може містити будь який тип даних.
Доступ до властивостей та методів проводиться через крапку. Якщо це метод, він викликається з використанням дужок, якщо треба прочитати чи записати властивість - назва вказується без дужок.
let a = "текст"
console.log (a.toUpperCase());//ТЕКСТ, виклик методу toUpperCase(усі прописні) з дужками
console.log (a.length); //5, читання властивості length(довжини) без дужок
До імен властивостей, які не є дійсними ідентифікаторами, не можна отримати доступ до властивості через крапку (.
), але можна можна це зробити через квадратні лапки (“[]
”).
let unPropNames = {
'': 'An empty string',
'!': 'Bang!'
}
console.log(unPropNames.''); // помилка SyntaxError: Unexpected string
console.log(unPropNames['']); // An empty string
console.log(unPropNames.!); // помилка SyntaxError: Unexpected token !
console.log(unPropNames['!']); // Bang!
Доступ через квадратні лапки також дає можливість доступатися до властивостей об’єкту через змінну або вираз.
let key = "likes birds";
user[key] = true; // те саме, що і user["likes birds"] = true;
let fruit = prompt("Який фрукт купити?", "apple");
let bag = {
[fruit]: 5, // ім'я властивості буде взято зі змінної fruit
};
Крім великої кількості існуючих системних і бібліотечних об’єктів, можна використовувати свої об’єкти. Об’єкт можна створити через конструктор, або через літерал.
let user = new Object(); // синтаксис "конструктор об'єкта"
let user = {}; // синтаксис "літерал об'єкта"
Використання new вказує, що необхідно використати спеціальну функцію-конструктор з назвою Object
. Конструктор Object
створює об’єкт-обгортку для переданого значення. Якщо значенням є null
або undefined
, він створює і повертає порожній об’єкт, в іншому випадку — повертає об’єкт такого типу, який відповідає переданому значенню.
Специфікатор new
може також використовуватися для виклику інших конструкторів (не Object
) - функцій, в яких прописуються інструкції створення об’єкту. Так досягається прототипування об’єктів, так як в конструкторі можна задати всю структуру об’єкту для всіх екземплярів. Детальніше про створення таких конструкторів буде в наступній лекції. Тут розглянемо використання існуючих конструкторів на прикладі Date
.
const datebd = new Date('1978/10/23 03:45:00'); //день народження
let now = new Date(); //зараз
let myAge = parseInt (now - datebd)/(1000*60*60*24);//мс*с*хв*год*доба
console.log (myAge); //кількість днів
У розділі роботи з масивами також розглянемо використання вбудованого конструктору Array
для роботи з масивом.
Об’єктні літерали - це список з нуля або більше пар імен властивостей та методів об’єкту та асоційованих з ними значень, взятих у фігурні дужки ({}
). Властивості, які також називають полями, мають ключ, який також називають ім’ям або ідентифікатором. Використовуючи літеральний синтаксис об’явлення можна одразу в об’єкт помістити кілька властивостей і методів через пару “ключ
: значення
”. Значення може бути будь якого типу, в тому числі об’єктом. Наприклад:
var sales = 'Toyota';
function carTypes(name) {
if (name === 'Honda') {
return name;
} else {
return "Вибачте, ми не продаємо " + name + ".";
}
}
var car = { myCar: 'Saturn', //властивість - літерал
getCar: carTypes('Honda'),//властивість - результат функції
special: sales }; //властивість - змінна
console.log(car.myCar); // Saturn
console.log(car.getCar); // Honda
console.log(car.special); // Toyota
Добавлення властивостей чи методу може проводитися у будь який момент часу, достатньо до них звернутися для записування.
let a = {p1 : 10}; //створили об'єкт з однією властивістю
a.p2 = 11; //добавили нову властивість зі значенням 11
a.sum = function (a) {return this.p1 + this.p2 + a};//добавили новий метод, що повертає суму
console.log (a.sum(2)); //виведе 23
Видалення властивостей чи методу проводиться через delete
delete a.sum;
Можна використовувати числовий або рядковий літерал для назви властивості, або вкладати об’єкт всередину іншого. У наступному прикладі використовуються ці можливості.
let car = { manyCars: {a: 'Saab', b: 'Jeep'}, 7: 'Mazda' };
console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda
Імена властивостей об’єкта можуть бути будь-якими рядками, включаючи порожні. Якщо ім’я властивості не є дійсним ідентифікатором (не за правилами найменування змінних, наприклад включає пробіли) чи числом JavaScript, воно повинно бути вставлено в лапки.
Якщо необхідно властивості надавати значення з тим самим іменем, його можна не вказувати:
function makeUser(name, age) {
return {
name, // те саме, що і name: name
age // те саме, що і age: age
// ...
};
}
Присвоєння для об’єктів працює не як дублювання змісту, а як копіювання за посиланням на той же самий об’єкт. Порівняння об’єктних змінних ==
або ===
показує, що ці змінні посилаються на той же об’єкт. Тобто:
let user = { name: "John" };
let admin = user; // це друга змінна, яка посилається на той же об'єкт
console.log (admin === user); //true
user.lastname = "Smith"; // нова властивість для user
console.log (admin.lastname); //Smith, те саме значення бо це той же об'єкт
Оператор in
повертає true
, якщо вказана властивість або метод існує у вказаному об’єкті. Наприклад:
console.log ("log" in console);//true
console.log ("Log" in console);//false
Оператор instanceof
повертає true
, якщо вказаний об’єкт належить до вказаного типу. Наприклад:
let now = new Date();
let now1 = {DT:"2020/04/15 20:15:00"}
console.log (now instanceof Date); //true
console.log (now1 instanceof Date); //false
for..in
)Перебір усіх властивостей та методів проводиться через for..in
let obj = {a: 1, b: 2, c: 3};
for (const prop in obj) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
// Виведе:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
...
)Синтаксис ...
перед об’єктами в JavaScript використовується для розширення об’єктів (Object Spread). Він дозволяє копіювати властивості з одного об’єкта в інший об’єкт або об’єднувати властивості з кількох об’єктів в один об’єкт.
Основні використання синтаксису ...
перед об’єктами:
1) Копіювання об’єкта: За допомогою ...
можна швидко створити поверхневу копію об’єкта, копіюючи всі його властивості в новий об’єкт.
const obj1 = { x: 1, y: 2 };
const obj2 = { ...obj1 };
console.log(obj2); // { x: 1, y: 2 }
2) Об’єднання об’єктів: За допомогою ...
можна об’єднати властивості з кількох об’єктів в один об’єкт.
javascript
const obj1 = { x: 1 };
const obj2 = { y: 2 };
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj); // { x: 1, y: 2 }
3) Додавання нових властивостей: За допомогою ...
можна додавати нові властивості до об’єкта.
javascript
const obj1 = { x: 1 };
const obj2 = { ...obj1, y: 2 };
console.log(obj2); // { x: 1, y: 2 }
Зверніть увагу, що синтаксис ...
перед об’єктами доступний з ECMAScript 2018 (ES9) і пізнішими версіями JavaScript.
keys()
Метод Object.keys()
використовується для отримання масиву, що містить імена всіх перераховуваних властивостей об’єкту. Ось приклад використання методу Object.keys()
:
const obj = { a: 1, b: 2, c: 3 };
const keys = Object.keys(obj);
keys.forEach(function(key) {
console.log(key + ': ' + obj[key]);
});
У цьому прикладі ми спочатку використовуємо Object.keys(obj)
, щоб отримати масив, що містить імена всіх властивостей об’єкту obj
. Потім ми використовуємо forEach()
для ітерації по цьому масиву і виведення кожної властивості та її значення. Результат буде наступним:
a: 1
b: 2
c: 3
Цей підхід дозволяє перебрати усі перераховувані властивості об’єкту, незалежно від того, чи є вони власними властивостями об’єкту чи успадкованими. Зауважте, що метод Object.keys()
повертає тільки перераховувані властивості, а не властивості, що не перераховуються (наприклад, властивості, що використовуються для зберігання внутрішніх станів об’єкту).
Є кілька способів об’єднати два об’єкти в JavaScript. Один з них - використання методу Object.assign()
, який дозволяє об’єднати властивості з одного або кількох об’єктів в один об’єкт. Наприклад:
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const obj3 = Object.assign({}, obj1, obj2);
console.log(obj3); // { a: 1, b: 2, c: 3, d: 4 }
У цьому прикладі ми створили два об’єкти obj1
і obj2
, а потім об’єднали їх в один об’єкт obj3
, використовуючи метод Object.assign()
. Першим параметром методу є пустий об’єкт {}
, який буде місцем призначення для об’єднаних властивостей. Потім ми передаємо об’єкти, які ми хочемо об’єднати, як наступні параметри методу.
Є й інші способи об’єднати об’єкти, такі як оператор spread (...)
або методи Object.keys()
, Object.values()
та Object.entries()
, але метод Object.assign()
є простим і ефективним способом зробити це.
Але Object.assign()
об’єднує властивості тільки на одному рівні. Для об’єднання об’єктів на всіх рівнях вкладеності можна використовувати рекурсію. Можна написати функцію, яка проходиться по всіх властивостях об’єкту та рекурсивно викликає себе для кожної властивості, що також є об’єктом.
Ось приклад функції, яка об’єднує два об’єкти на всіх рівнях вкладеності:
function mergeObjects(obj1, obj2) {
// перебираємо всі властивості obj2
for (let prop in obj2) {
if (obj2.hasOwnProperty(prop)) {
// якщо властивість є об'єктом, рекурсивно викликаємо mergeObjects
if (typeof obj2[prop] === 'object') {
// якщо властивість також є об'єктом, викликаємо mergeObjects
if (typeof obj1[prop] === 'object') {
obj1[prop] = mergeObjects(obj1[prop], obj2[prop]);
} else {
obj1[prop] = obj2[prop];
}
} else {
obj1[prop] = obj2[prop];
}
}
}
return obj1;
}
Ця функція бере два об’єкти як аргументи, а потім перебирає всі властивості другого об’єкта. Якщо властивість є об’єктом, то викликає саму себе рекурсивно з відповідними властивостями першого та другого об’єкта. Якщо властивість не є об’єктом, то просто копіюємо її з другого об’єкта в перший. Значення властивостей другого об’єкта будуть переписувати властивості першого.
Наприклад, якщо ми маємо два об’єкти:
let obj1 = {
a: {b: 1,c: 2},
d: 3
};
let obj2 = {
a: {b: 4, e: 5},
f: 6
};
Тоді можемо об’єднати їх, викликавши функцію mergeObjects:
let result = mergeObjects(obj1, obj2);
console.log(result);
Результатом буде об’єкт:
{
a: {b: 4, c: 2,e: 5},
d: 3,
f: 6
}
У JavaScript немає явного типу даних для масиву. Для роботи з масивами можна використовувати заздалегідь заданий об’єкт Array
та його методи.
Об’єкт Array
має ряд властивостей, наприклад довжину (length
) та методи маніпулювання масивами, такі як з’єднання(joining), реверсування(reversing), сортування та інші.
У масиві можна зберігати елементи різного типу. Створення масиву можна проводити кількома способами. Наступні операції створюють еквівалентні масиви:
let arr1 = new Array(3, '19', {a: 35});
let arr2 = Array(3, '19', {a: 35});
let arr3 = [3, '19', {a: 35}];
Для створення масиву з ненульовою довжиною, але без будь-яких елементів, може бути використане будь-яка з наведених нижче інструкцій:
let arLength = 3;
let arr1 = new Array(arLength);
let arr2 = Array(arLength);
// Це має точно такий же ефект
let arr3 = []; arr3.length = arLength;
На рівні реалізації масиви JavaScript фактично зберігають свої елементи як стандартні властивості об’єкта, використовуючи індекс масиву як ім’я властивості.
До елементу масиву звертаються за його індексом у квадратних дужках.
let fruits = ["Яблуко", "Апельсин", "Слива"];
console.log( fruits[0] ); // Яблуко
fruits[2] = 'Груша'; // зміна елементу
console.log (fruits ); //Array(3) ["Яблуко", "Апельсин", "Груша"]
console.log( fruits.length); // 3
fruits[3] = 'Лимон'; //добавлення нового елементу
console.log (fruits ); // Array(4) ["Яблуко", "Апельсин", "Груша", "Лимон"]
console.log( fruits.length); // 4
Властивість length
завжди повертає індекс останнього елементу плюс один. У властивість length
можна також записувати значення, що задає кількість елементів. Введення значення, коротшого за кількість збережених елементів, скорочує масив. Написання 0
спустошує масив повністю.
Для перебору елементів масиву можна використовувати операції for
.
В JavaScript є спеціальний оператор ...
(spread operator), який дозволяє розгорнути масив або інший ітерабельний об’єкт на окремі елементи. Це дозволяє легко комбінувати елементи з одного масиву з іншим масивом або додавати додаткові елементи в середину масиву.
Ось приклад використання оператора spread для з’єднання двох масивів:
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
У цьому прикладі ми створили два масиви arr1
та arr2
. За допомогою оператора spread ми розгорнули обидва масиви в окремі елементи та об’єднали їх в один новий масив combined
. Результатом є новий масив, який містить елементи з arr1
та arr2
.
Оператор spread також можна використовувати для передачі аргументів до функції:
function sum(a, b, c) {
return a + b + c;
}
const numbers = [1, 2, 3];
const result = sum(...numbers);
console.log(result); // 6
Можна створювати та працювати з багатовимірними масивами. Наступний код створює багатовимірний масив.
let a = new Array(4)
for (let i = 0; i < 4; i++) {
a[i] = new Array(4)
for (let j = 0; j < 4; j++) {
a[i][j] = '[' + i + ', ' + j + ']'
}
}
let ar1 = [[1,2,3],[4,5,6]];//двовимірний масив розмірність 2 на 3
console.log (ar1.length); //2
console.log (ar1[0].length);//3
console.log (ar1[1]); //Array(3) [4, 5, 6]
console.log (ar1[1][1]); //5
У таблиці нижче наведений перелік деяких методів та властивостей масивів. Повний перелік можна знайти за цим посиланням . Деякі з цих методів описані нижче.
Таблиця 2.1. Деякі з методів масивів.
Метод | Призначення |
---|---|
concat | поєднання масивів |
copyWithin | додає дрібну копію частини масиву в іншу позицію в тому ж масиві |
entries | повертає новий об’єкт ітератора масиву (Array Iterator), який містить пари ключ-значення для кожного індексу в масиві. |
every | перевіряє, чи всі елементи масиву відповідають умові, що задана функцією, яка передається як аргумент |
fill | заповнює (змінює) всі елементи масиву з початкового індексу до кінцевого статичним значенням |
filter | створює новий масив з усіма елементами, що пройшли перевірку вказаною функцією |
find | повертає значення першого елемента в масиві, що задовільняє передану функцію тестування |
findIndex | повертає індекс першого елемента у масиві, який задовольняє надану перевірочну функцію |
flat | створює новий масив який містить всі елементи вкладених масивів до вказаної глибини |
flatMap | аналогічно послідовному виклику map() та flat() з глибиною 1 |
forEach | виконує надану функцію один раз для кожного елемента масиву |
from | створює новий екземпляр Array з подібного до масиву або ітерабельного об’єкта |
includes | з’ясовує, чи масив містить елемент із вказаним значенням |
indexOf | повертає перший індекс, за яким даний елемент був знайдений в масиві |
isArray | з’ясовує, чи є передане значення є масивом |
join | створює та повертає рядок, що об’єднує всі елементи масиву |
keys | вертає новий об’єкт перебирача ключів (індексів) масиву |
lastIndexOf | повертає останній індекс, за яким заданий елемент було знайдено у масиві |
length | встановлює або повертає кількість елементів у цьому масиві |
map | створює новий масив з результатами виклику наданої функції на кожному елементі масиву |
of | створює новий екземпляр Array з заданої кількості аргументів |
pop | видаляє останній елемент масиву та повертає цей елемент |
prototype |
Дозволяє додавати властивості до масивів. |
push | додає один або більше елементів у кінець масиву та повертає нову довжину масиву |
reduce | виконує вказану функцію для кожного елемента масиву та повертає єдине значення |
reduceRight | застосовує функцію до акумулятора та кожного елемента масиву (справа наліво), зменшуючи його до єдиного значення |
reverse | транспонує масив , змінюючи послідовність елементів на протилежну |
shift | видаляє перший елемент з масиву і повертає цей елемент |
slice | повертає дрібну копію частини масиву у новий масив |
some | з’ясовує, чи містить масив хоч один елемент, для якого зазначена функція |
sort | відсортовує елементи масиву |
splice | змінює вміст масиву, видаляючи існуючі та/або додаючи нові елементи |
toLocaleString | повертає рядок, що відображає елементи масиву |
toSource | повертає рядкове представлення першокоду масиву |
toString | повертає рядкове представлення заданого масиву та його елементів |
unshift | додає один або декілька елементів на початок масиву |
values | повертає новий об’єкт ітератора масиву (Array Iterator), який містить значення кожного елемента масиву |
for..of
Окрім for
, інструкції For..of
перебирають елементи в ітерабельних (перелічувальних) змінних (масивах, рядках) .
let fruits = ["Яблуко", "Апельсин", "Слива"];
for (let fruit of fruits) {
console.log (fruit);
}
let iterable = 'ой';
for (let value of iterable) {
console.log(value);
}
forEach()
Метод forEach()
в JavaScript використовується для ітерації (перебору) елементів масиву і виклику заданої функції з кожним елементом масиву. Синтаксис методу forEach()
виглядає наступним чином:
array.forEach(function(element, index, array) {
// код для обробки кожного елемента
});
У цьому синтаксисі:
array
- масив, який ми перебираємоelement
- поточний елемент масиву, який обробляється на кожній ітераціїindex
(опціонально) - індекс поточного елемента масивуarray
(опціонально) - сам масив, який перебираєтьсяФункція, передана в метод forEach()
, викликається для кожного елемента масиву один раз. Вона може містити код для обробки або виконання певних дій з кожним елементом масиву. Ось невеликий приклад використання методу forEach()
:
const array = [1, 2, 3, 4, 5];
array.forEach(function(element) {
console.log(element);
});
В цьому прикладі кожен елемент масиву буде виведений на консоль. Результатом буде:
1
2
3
4
5
Метод forEach()
виконує ітерацію по всіх елементах масиву в порядку їх послідовності. Він не повертає новий масив, а просто виконує дії з кожним елементом. Зауважте, що метод forEach()
не може бути припинений раніше, тобто немає можливості використовувати break
або return
для припинення його виконання. Якщо вам потрібно припинити ітерацію, вам може знадобитися використовувати цикл for
або while
з відповідними умовами перевірки
Оператор delete
може видалити елемент за вказаним індексом у масиві. Наприклад:
let fruits = ["Яблуко", "Апельсин", "Слива"];
delete fruits[1];
console.log( fruits); // Array(3) ["Яблуко", …, "Слива"]
console.log( fruits[1]);//undefined
Зверніть увагу, що кількість елементів в масиві залишилася незмінною, а елемент з індексом 1
став undefined
.
Масиви в JavaScript підтримують методи роботи як з чергами, так і з стеками:
push
добавляє один або кілька елементів в кінець масиву,pop
видаляє останній елемент з масивуshift
- видаляє елемент на початку масиву, здвигаючи чергу таким чином, що другий елемент стає першимunshift
- додає один або декілька елементів на початок масивуlet fruits = ["Яблуко", "Апельсин", "Груша"];
fruits.pop(); console.log(fruits); // Array(2) ["Яблуко", "Апельсин"]
fruits.push("Груша"); console.log(fruits); // Array(3) ["Яблуко", "Апельсин", "Груша"]
fruits.shift(); console.log(fruits); //Array(2) ["Апельсин", "Груша"]
fruits.unshift("Яблуко"); console.log(fruits);//Array(3) ["Яблуко", "Апельсин", "Груша"]
рис.2.6. Порівняння швидкості роботи методів добавлення та видалення елементів з масивів.
Можна добавляти кілька елементів
let fruits = ["Яблуко"];
fruits.push("Апельсин", "Груша");
fruits.unshift("Ананас", "Лимон");
console.log(fruits); //Array(5) ["Ананас", "Лимон", "Яблуко", "Апельсин", "Груша"]
Слід звернути увагу на те, що методи push/pop
виконуються швидше ніж shift/unshift
.
Якщо необхідно видалити елемент масиву в середині масиву, можна скористатися його методами: splice) або slice.
Метод splice
змінює вміст масиву, видаляючи існуючі та/або додаючи нові елементи.
//Видалення 2-ох елементів, починаючи з індексу 2
let myFish = ['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon'];
let removed = myFish.splice(2, 2);
console.log (myFish);// ["parrot", "anemone", "sturgeon"]
console.log (removed);// ["blue", "trumpet"]
//Видалення 0 елементів, починаючи з індексу 2, і вставлення "drum"
myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
removed = myFish.splice(2, 0, 'drum');
console.log (myFish);// ["angel", "clown", "drum", "mandarin", "sturgeon"]
console.log (removed);// нічого не виведе, жодний елемент не було видалено
Метод slice
повертає дрібну копію частини масиву у новий масив, починаючи з begin
і до end
(не включаючи end
), де begin
та end
є індексами елементів масиву. Початковий масив не змінюється.
map
)Метод map()
є одним з найбільш корисних методів масивів у JavaScript. Він створює новий масив, використовуючи результати виклику зазначеної функції з кожним елементом вихідного масиву.
Синтаксис методу map()
виглядає наступним чином:
array.map(function(currentValue, index, array) {
// повертає елементи для нового масиву
})
Цей метод приймає функцію, яка викликається для кожного елемента вхідного масиву. Функція повинна повертати значення для нового масиву. Опціональні параметри функції - це значення поточного елемента (currentValue
), індекс поточного елемента (index
) та вихідний масив (array
).
Приклад використання методу map()
:
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = numbers.map(function(num) {
return num * 2;
});
console.log(doubledNumbers); // [2, 4, 6, 8, 10]
У цьому прикладі ми маємо масив чисел numbers
. Ми викликаємо метод map()
на цьому масиві і передаємо функцію, яка повертає кожен елемент, помножений на 2. Результатом є новий масив зі значеннями [2, 4, 6, 8, 10]
, що містить усі елементи вихідного масиву, помножені на 2.
some
)Метод some
є вбудованим методом масиву і використовується для перевірки, чи задовольняє хоча б один елемент масиву певному умовному виразу. Синтаксис методу some
виглядає наступним чином:
array.some(callback(element[, index[, array]])[, thisArg])
callback
- Функція, яка буде викликана для кожного елемента масиву. Вона приймає три аргументи: element
(поточний елемент масиву), index
(індекс поточного елемента) і array
(сам масив).thisArg
(необов’язковий) - Значення, яке буде використовуватися як this
в тілі функції callback
.Метод some
повертає булеве значення true
, якщо хоча б один елемент масиву задовольняє умову виразу в callback
. В іншому випадку, якщо жоден елемент не задовольняє умову, повертається false
.
Отримання результату методу some
можна використовувати для прийняття рішень, перевірки умови наявності певного елемента в масиві або фільтрації масиву за певною умовою.
Звичайний приклад використання методу some
може виглядати так:
const numbers = [1, 2, 3, 4, 5];
// Перевіряємо, чи є хоча б одне парне число в масиві
const hasEvenNumber = numbers.some(num => num % 2 === 0);
console.log(hasEvenNumber); // true
У цьому прикладі ми використовуємо метод some
, щоб перевірити, чи є хоча б одне парне число в масиві numbers
. Функція num => num % 2 === 0
виконує перевірку на парність чисел. Оскільки у масиві є число 2, яке задовольняє умову, метод some
повертає значення true
.
Метод filter
використовується для створення нового масиву, в якому знаходяться елементи вихідного масиву, що відповідають певному умовному виразу. Синтаксис методу filter
:
const newArray = array.filter(callback(element, index, array));
Де:
array
- вихідний масив, з якого будуть відфільтровані елементи.callback
- функція, що означує умову фільтрації для кожного елемента.element
- поточний елемент масиву, який перевіряється функцією callback
.index
(опціональний) - індекс поточного елемента масиву.array
(опціональний) - посилання на вихідний масив, з якого виконується фільтрація.Функція callback
повертає true
для елементів, які мають бути включені у новий масив, і false
для елементів, які мають бути виключені.
Ось приклад використання методу filter
:
const numbers = [1, 2, 3, 4, 5];
// Фільтруємо парні числа
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4]
У цьому прикладі ми використовуємо метод filter
, щоб створити новий масив evenNumbers
, який містить лише парні числа з вихідного масиву numbers
. Функція num => num % 2 === 0
виконує перевірку на парність чисел. Як результат, новий масив evenNumbers
містить елементи [2, 4]
, оскільки ці числа задовольняють умову.
=>
Вище було розглянуто два синтаксиса створення функцій - шляхом оголошення та за допомогою функціонального виразу. Ще одним синтаксисом створення функцій подібно до функціонального виразу є «функції-стрілки» або «стрілочні функції» (arrow functions).
let sum1 = (a, b) => a + b; //стрілочна функція
let sum2 = function(a, b) {return a + b};//аналогічна форма через функціональний вираз
console.log(sum1(1, 2) ); // 3
console.log(sum2(1, 2) ); // 3
При використанні одного аргументу, запис буде ще коротше:
let double1 = function(n) { return n * 2 }
let double2 = n => n * 2; //анаогічний попередньому
Якщо немає аргументів, це матиме вигляд:
let sayHi = () => console.log("Hello!");
Такі функції зручні для простих однорядкових дій. Однак вони мають додаткові можливості, які наразі розглядати не будемо.
arguments
Якщо кількість аргументів може варіюватися, тобто якісь з аргументів не є обов’язковими, можна скористатися залишковими параметрами. Залишкові параметри (rest parameters) - це представлення усіх фактичних параметрів при виклику функції у вигляді одного масиву. При означенні функції, ці параметри вказуються після ...
і якщо використовуються, повинні бути в кінці списку параметрів. Після залишкових параметрів не можна вказувати інші.
function showName(firstName, lastName, ...titles) { //titles - масив залишкових параметрів
console.log( firstName + ' ' + lastName ); // Юлій Цезарь
// Інші параметри підуть в масив
// titles = ["Консул", "Імператор"]
console.log( titles[0] ); // Консул
console.log( titles[1] ); // Імператор
console.log( titles.length ); // 2
}
showName("Юлій", "Цезарь", "Консул", "Імператор");
Усі аргументи функції знаходяться в псевдо-масиві arguments
під своїми порядковими номерами. Зрештою, при оголошенні функції, аргументи можна взагалі не вказувати і перебирати їх через arguments
.
function showName() { //формальні параметри не вказуються
console.log (arguments.length); //4
for (let arg of arguments)
{
console.log(arg); // послідовно буде виводити усі аргументи
}
}
showName("Юлій", "Цезарь", "Консул", "Імператор");
Багато функцій JavaScript та його середовищ виконання одразу повертають результат, ще до того як вона виконала цільову дію. Це корисно тоді, коли завершення обробки функції займає багато часу, яке при очікуванні буде гальмувати виконання програми.
Наприклад, функція setTimeout
повинна виконати якусь дію через вказаний інтервал часу. Для того щоб вказати цю дію, вона записується як інструкції в функції, яка буде викликатися через цей інтервал. Наприклад:
let fn = function () {console.log ("пройшло 2 секунди")};
console.log ("Запускаємо таймер");
setTimeout(fn, 2000);
console.log ("Таймер запущено, чекаємо...");
У даному прикладі, функція fn
містить інструкцію, яку необхідно виконати через 2 секунди. При виклику setTimeout
ця функція передається в якості аргументу разом з інтервалом (задається в мілісекундах). Замість того, щоб чекати 2 секунди, функція setTimeout
одразу обробляється і передає керування наступній інструкції, що йде за нею. У цей час десь на рівні ОС запускається окремий програмний потік, задача якого відслідкувати спрацювання таймеру. Однак цей потік не зупиняє виконання програми JavaScript, вона виконується далі. Коли системний потік з таймером виявить, що час пройшов, він викличе функцію fn
.
Таким чином наведена вище програма спочатку виведе повідомлення “Запускаємо таймер”, потім “Таймер запущено, чекаємо…” і через 2 секунди “пройшло 2 секунди”. Така функція, яка запускається на виконання, одразу віддає керування потоку, що її визвав, ще до завершення результату називається асинхронною. Функція, яка передається в якості аргументу для її виклику називається функцією зворотного виклику (колбек, callback). У наведеному вище прикладі функція setTimeout
є асинхронною, а fn
- функцією зворотного виклику.
Наведений вище код з використанням функцій стрілок може виглядіти наступним чином:
console.log ("Запускаємо таймер");
setTimeout(() => console.log ("пройшло 2 секунди"), 2000);
console.log ("Таймер запущено, чекаємо...");
Асинхронно також працює функція setInterval
, яка запускає функцію, з вказаною періодичністю:
let fn = function () {console.log ("пройшло 2 секунди")};
console.log ("Запускаємо таймер");
setInterval(fn, 2000);
console.log ("Таймер запущено, чекаємо...");
Асинхронність є дуже корисною характеристикою тих функцій, які працюють з зовнішніми засобами. Якщо дані необхідно кудись записати, скільки це займе часу. Нижче наведений приклад, де показані в тактах ЦПУ час, що потребується для цього (числа умовні, але порядок буде такий самий).
Таблиця 14.1. Порівняльна таблиця часу, який необхідний для виконання різних операцій.
Операція запису в | Кількість тактів CPU (приблизно) |
---|---|
CPU Registers | 3 такти |
L1 Cache | 8 тактів |
L2 Cache | 12 тактів |
RAM | 150 тактів |
Диск | 30,000,000 тактів |
Мережа | 250,000,000 тактів |
Якщо б операції доступу (читання/запису) по мережі до даних реалізовувалися через синхронні функції, програмний потік JavaScript просто б постійно зависав. Замість цього асинхронна функція запускається з передачею функції зворотного виклику і програма далі працює. У цей час ОС виконує необхідну операцію. Як тільки вона буде оброблена, буде викликана функція зворотного виклику.
Конструктор Function
створює новий об’єкт Function
. Прямий виклик конструктора може створювати функції динамічно, але має проблеми з безпекою та схожі з eval
(але менш значні) проблеми з продуктивністю. Однак, на відміну від eval
, конструктор Function
створює функції, які виконуються тільки у глобальній області видимості.
new Function (arg1, arg2, ...argN,functionBody)
arg1, arg2, ... argN
- імена, які будуть використані функцією в якості імен формальних аргументів. Кожне ім’я має бути рядком, який представляє ідентифікатор JavaScript, або списком таких рядків, розділених комою; наприклад, “x
”, “theValue
” або “a,b
”.functionBody
- рядок, що містить інструкції JavaScript, які складають означення цієї функції.//у змінній strfn знаходиться код функції
let strfn = "let y = a+b+c; console.log ('Значення суми = ' + y + '!')";
let fno = new Function ("a","b","c", strfn);
fno (100,10,1); //Значення суми = 111!
Додатково про це можна прочитати за цим або за цим посиланням.
Додатково про властивості і методи функцій як об’єктів наведено нижче.
На минулій лекції були коротко розглянуті призначення об’єктів, їх створення через літерал та робота з властивостями та методами. Тут продовжимо розглядати об’єкти та їх призначення.
Окрім властивостей об’єктів, які надають можливість доступитися до певного його параметру, можна користуватися певними діями, які може робити об’єкт. Такі дії в JavaScript представлені властивостями-функціями об’єкта.
let user = {
name: "Джон",
age: 30
};
user.sayHi = function() {
console.log("Привіт!");
};
user.sayHi(); // Привіт!
У наведеному вище прикладі властивості user.sayHi
об’єкта був присвоєний функціональний вираз (Function Expression). Тепер цю властивість можна використовувати для виклику функції. Властивості-функції об’єкту називають методом цього об’єкту.
Альтернативний спосіб через оголошення функції матиме вигляд:
let user = {
name: "Джон",
age: 30
};
// спочатку оголошуємо
function sayHi() {
console.log("Привіт!");
};
// потім добалвяємо в якості метода
user.sayHi = sayHi;
user.sayHi(); // Привіт!
Існують також короткі синтаксиси для методів при створенні об’єктів через літерал:
let user1 = {
sayHi: function() { //метод створюється при створенні об'єкту
console.log("Привіт!");
}
};
let user2 = {
sayHi() { // те саме, що і "sayHi: function()"
console.log("Привіт!");
}
};
user1.sayHi();user2.sayHi();
До методів об’єктів також можна доступатися не тільки через крапку, але і через прямокутні дужки, адже це також властивості. Це дає можливість вказувати метод через змінну, наприклад:
let user = {
sayHi() {console.log("Привіт!")}
};
let method = "sayHi";
user[method]();
Слід звернути увагу, що звернення до методу без дужок, значить звернення до самої функції, а не її виклик, наприклад.
let user = {
sayHi() {console.log("Привіт!")}
};
let method = user.sayHi; //назначаємо змінній функцію
method(); //викликаємо функцію - Привіт!
console.log (user.sayHi);//sayHi() { … }
console.log (method); //sayHi() { … }
this
Як правило, методу об’єкта необхідний доступ до інформації, яка зберігається в об’єкті, щоб виконати з нею які-небудь дії (у відповідності з призначенням методу). Наприклад, коду в об’єкті необхідний доступ до інформації, яка зберігається в тому ж об’єкті, щоб виконати з нею які-небудь дії (у відповідності з призначенням методу). Наприклад, коду всередині user.sayHi()
може знадобитися ім’я користувача, яке також зберігається в цьому об’єкті.
Для того щоб звернутися до свого ж об’єкту, використовується ключове слово this
. Наприклад,
let user = {
name: "Джон",
age: 30,
sayHi() {
// this - це "плинний об'єкт"
console.log("Привіт, мене звати " + this.name + " !");
}
};
user.sayHi(); // Привіт, мене звати Джон !
Тут під час виконання user.sayHi()
значеннямthis
буде user
(посилання на об’єкт user
). Можна також звертатися безпосередньо до об’єкту user
, але назва об’єкту може бути різною, а нас цікавить саме цей об’єкт, в якому викликається метод.
Значення this
розраховується під час виконання і залежить від контексту.
Літеральний синтаксис {...}
дозволяє створювати один унікальний об’єкт. Але часто необхідно створити багато однотипних об’єктів. Це можна робити з використанням функції-конструктора і ключового слова new
.
Функції-конструктори призначені для побудови об’єктів. До них є певні вимоги:
new
Коли функція викликається як new User(...)
, відбувається наступне:
this
this
, добавляє туди нові властивостіthis
Іншими словами, виклик new User(...)
робить приблизно наступне:
function User(name) {
// this = {}; (неявно)
// добавлення властивостей, методів і додаткові дії інціалізації і т.п.
this.name = name;
this.isAdmin = false;
// return this; (неявно)
}
let user = new User("Вася");
console.log(user.name); // Вася
console.log(user.isAdmin); // false
Таким чином, результат виклику new User("Вася")
буде той самий об’єкт, що і
let user = {
name: "Вася",
isAdmin: false
};
Однак, на відміну від літерального способу, створення об’єктів з такими самими властивостями тепер зводиться до виклику функції-конструктора, а не до повторення літералів.
// літеральний
let user1 = {name: "Вася",isAdmin: false};// для кожного користувача повний перелік властивостей
let user2 = {name: "Міша", isAdmin: false};
//через конструктор
function User(name) { this.name = name; this.isAdmin = false} // один конструктор
let user3 = new User("Вася");//створення властивостей для кожного користувача через виклик конструктору
let user4 = new User("Міша");
Не важко помітити, що коли кількість властивостей та об’єктів зростає, використання конструктору значно спрощує створення однотипних об’єктів. Функція-конструктор призначена і використовується саме для створення об’єктів.
Якщо в функції-конструкторі повертається значення через return
це повинно бути об’єктною змінною, інакше буде повернено this
.
У конструкторі можна також створювати методи.
function User(name) {
this.name = name;
this.sayHi = function() {console.log( "Мене звати " + this.name )};
}
let user1 = new User("Вася");
user1.sayHi(); // Мене звати: Вася
Для складних об’єктів є ще один синтаксис - класи, які у даному курсі не будуть розглядатися.
Об’єкт Object
є вбудованим типом даних у JavaScript, який дозволяє зберігати дані у вигляді пар ключ-значення. Він має багато методів та властивостей, які можуть бути використані для роботи з об’єктами. Ось кілька найбільш вживаних методів та властивостей об’єкта:
Object.keys(obj)
: Повертає масив, що містить всі ключі (властивості) об’єкта obj
.Object.values(obj)
: Повертає масив, що містить всі значення властивостей об’єкта obj
.Object.entries(obj)
: Повертає масив, що містить всі пари ключ-значення властивостей об’єкта obj
.Object.assign(target, source)
: Копіює властивості з одного або кількох джерел (source
) до цільового об’єкта (target
), повертаючи змінений цільовий об’єкт.Object.hasOwnProperty(prop)
: Перевіряє, чи має об’єкт властивість з ім’ям prop
. Повертає true
, якщо така властивість існує безпосередньо в об’єкті, і false
- в іншому випадку.Object.create(proto)
: Створює новий об’єкт з вказаним прототипом proto
.Object.defineProperty(obj, prop, descriptor)
: Додає або змінює властивість prop
об’єкта obj
, використовуючи вказаний дескриптор descriptor
.Object.freeze(obj)
: Заморожує об’єкт obj
, що робить його властивості недоступними для зміни або видалення.Object.seal(obj)
: Запечатує об’єкт obj
, що дозволяє змінювати значення властивостей, але не дозволяє додавати нові або видаляти існуючі властивості.Object.getPrototypeOf(obj)
: Повертає прототип об’єкта obj
.Функція Object.values(x)
використовується для отримання масиву, що містить значення властивостей об’єкта x
. Вона повертає новий масив, який містить значення у тому ж порядку, в якому вони перераховані в об’єкті.
Наприклад, розглянемо наступний об’єкт:
const person = {
name: 'John',
age: 30,
profession: 'Engineer'
};
const values = Object.values(person);
console.log(values);
// Вивід: ['John', 30, 'Engineer']
У JavaScript є багато вбудованих об’єктів. У цьому розділі розглянемо кілька з них.
Вбудований об’єкт Number
представляє об’єкт-обгортку для змінних та констант однойменного типу. Будь які змінні та літерали можна використовувати як об’єкт Number
. Наприклад, можна звернутися до методу toString
літералу:
console.log ((255).toString(16)); // ff - 16-ковий формат
console.log ((0xFF).toString()); // 255 - 10-ковий формат
Об’єкт вміщує ряд властивостей, такі як масимальне числове значення, не-число(NaN) та безкінечність (infinity) та інші. У таблиці нижче деякі з них:
Таблиця 14.2. Властивості об’єкту Number
Властивість | Опис |
---|---|
Number.NaN |
Спеціальне значення “не-число” |
Number.NEGATIVE_INFINITY |
Спеціальне від’ємне безкінечне число; повертається при переповненні |
Number.POSITIVE_INFINITY |
Спеціальне додатне безкінечне число; повертається при переповненні |
Ви не можете змінювати значення цих властивостей, але можете використовувати їх для читання.
Об’єкт Number також надає множину методів для роботи з числами, зокрема:
Таблиця 14.3. Методи об’єкту Number
Метод | Опис |
---|---|
Number.parseFloat() |
Приймає рядок в якості аргументу та повертає число з плаваючою комою, яке вдалося розпізнати. Аналог глобальній функції parseFloat() . |
Number.parseInt() |
Приймає рядок в якості аргументу та поверає ціле число в заданій системі числення, якщо аргумент вдалося розпізнати. Аналог глобальній функції parseInt() . |
Number.isFinite() |
Визначає, чи передане значення є кінцевим числом. |
Number.isInteger() |
Визначає, чи передане число є цілим. |
Number.isNaN() |
Визначає, чи передане число є NaN . Більш надійніша версія оригінальної глобальної функції isNaN() . |
Number.isSafeInteger() |
Визначає, чи передане значення є числом, що є безпечним цілим. |
Nuber.toString(radix) | Вертає рядкове предствлення числа у вказаній у дужках (radix ) системі числення |
let a=0xF; //16-ковий формат
console.log (a.toString()); // 15 - 10-ковий формат
console.log (a.toString(2)); // 1111 - двійковий формат
console.log (a.toString(16)); // f - 16-ковий формат
Прототип Number
надає методи для отримання інформації з об’єкту Number
в різноманітних форматах. Наступній таблиці представлені методи з Number.prototype
.
Таблиця 14.4. Методи об’єкту Number.prototype.
Методи | Опис |
---|---|
toExponential(fractionDigits) |
Повертає рядок, що представляє число в експоненціальній нотації з fractionDigits цифр після коми |
toFixed(digits) |
Повертає рядок, що представляє число з плаваючою комою з digits цифр після коми |
toPrecision(precision) |
Повертає рядок, що представляє число із заданою точністю у позначені плаваючої коми з precision кількістю цифр. |
let numObj = 77.1234;
console.log(numObj.toExponential()); //'7.71234e+1'
console.log(numObj.toExponential(2)); //'7.71e+1'
console.log(numObj.toFixed()); // '77'
console.log(numObj.toFixed(1)); // '77.1'
console.log(numObj.toPrecision()) // '77.1234'
console.log(numObj.toPrecision(5)) // '77.123'
console.log(numObj.toPrecision(2)) // '77'
console.log(numObj.toPrecision(1)) // '8e+1'
Вбудований об’єкт Math
має властивості та методи для математичних констант та функцій.
На відміну від інших глобальних об’єктів, Math()
не є конструктором. Тобто необхідно використовувати безпосередньо методи об’єкту Math
.
let a = new Number();//так можна робити
console.log (a.toString());//0
let b = new Math(); // помилка Math is not a constructor
Всі поля і методи Math
статичні. Тобто до сталої Пі потрібно звертатись Math.PI
, а функцію синуса викликати через Math.sin(x)
, де x
є аргументом статичного методу. Всі константи задані із максимальною для дійсних чисел у JavaScript точністю.
Нижче наведені кілька властивостей та методів, усі інші можна подивитися у довіднику Через властивості доступні деякі константи, зокрема, які наведені в таб.14.5.
Таблиця 14.5. Константи Math.
Властивість | Опис |
---|---|
Math.E |
Стала Ейлера, основа натуральних логарифмів. Приблизно дорівнює 2.718. |
Math.PI |
Значення відношення довжини кола до його діаметру, наближено дорівнює 3.14159. |
Math.SQRT2 |
Значення квадратного кореня від 2, наближено 1.414. |
let a = Math.E;
console.log (a); //2.718281828459045
Математичні функції представлені через методи, які наведені у таблиці 14.6:
Таблиця 14.6. Методи об’єкту Math.
Метод | Опис |
---|---|
Math.asin(x) |
Повертає арксинус числа. |
Math.sin(x) |
Повертає значення синуса аргументу. Через аналогічні методи доступні усі тригонометричні функції |
Math.abs(x) |
Повертає абсолютне значення (модуль) числа. |
Math.sqrt(x) |
Повертає додатне значення квадратного кореня від аргументу. |
Math.cbrt(x) |
Повертає кубічний корінь числа. |
Math.pow(x, y) |
Повертає результат піднесення x до степеня y . |
Math.ceil(x) |
Повертає число, округлене “до більшого”. |
Math.floor(x) |
Повертає результат округлення “до меншого”, тобто відкидує дробову частину. |
Math.round(x) |
Повертає значення аргументу, округлене до найближчого цілого. |
Math.trunc(x) |
Повертає цілу частину аргументу, відкидаючи всю дробову частину. |
Math.log10(x) |
Повертає логарифм за основою 10 від аргументу. |
Math.random() |
Повертає псевдовипадкове число з-поміж 0.0 і 1.0. |
Math.sign(x) |
Повертає знак поданого числа. Визначає, чи являється аргумент додатним числом (вертає 1), від’ємним (вертає -1), чи дорівнює 0 (вертає 0). |
Варто зазначити, що тригонометричні функції (sin(), asin() ..) очікують або повертають значення у радіанах. Для конвертації достатньо пам’ятати, що 1 кутовий градус - це (Math.PI / 180) радіан.
console.log (Math.random()); //випадкове число від 0 до 1
console.log (Math.sin(Math.PI/10));//0.3090169943749474
console.log (Math.sign(-15.34)); //-1
JavaScript не має окремого типу даних для збереження дат. Тим не менше, для роботи з датою та часом можна використовувати об’єкт Date
та його методи . Він має велику кількість методів для встановлення, отримання та маніпулювання датами, але не має жодних властивостей.
JavaScript зберігають дату, як кількість мілісекунд, що минули з 00:00:00 1 січня 1970 року. Значення в часу в мілісекундах також називається TimeStamp.
Об’єкт Date
має окремі методи для підтримки UTC (всесвітній час) та місцевого часу. UTC (узгоджений всесвітній час) означає час встановлений світовим стандартом. Натомість місцевий час — це час того комп’ютера, на якому виконується код JavaScript.
Для того, щоб створити власний екземпляр об’єкту Date
можна викликати однойменний конструктор:
let dateObjectName = new Date([parameters]);
де dateObjectName
ім’я змінної в яку присвоюється створене значення з типом Date
; це може бути як новий об’єкт, або як властивість існуючого об’єкту.
parameters
(в наведеному вище синтаксисі) може бути представлений одним з наступних значень:
new Date();//Пусто: створюється сьогоднішня дата та час.
new Date(value);//кількість мілісекунд з 1970 - TimeStamp
new Date(dateString);//Набір цілих значень для року, місяця і дня
new Date(year, month[, day[, hours[, minutes[, seconds[, milliseconds]]]]]); //Набір цілих значень для року, місяця, дня, години, хвилини та секунди.
value
— ціле число, що вказує кількість мілісекунд з 1 січня 1970 року 00:00:00 за UTC без врахування високосних секунд. Це те саме, що час Unix, але зважайте на те, що більшість функцій часу й дати Unix рахують у секундах.
dateString
— Рядок, що вказує дату й час. Має бути у форматі, що розпізнається методом Date.parse()
(IETF-compliant RFC 2822 timestamps, і також різновид ISO8601).
Зверніть увагу, що month
задається від 0
(січень) до 11
(грудень)
Приклад:
let DT1 = new Date(); //теперішня дата
let DT2 = new Date(1587227373000);//TimeStamp
console.log (DT2); //Sat Apr 18 2020 19:29:33 GMT+0300 (GMT+03:00)
let DT3 = new Date("2020, 4, 18 19:29:33");
console.log (DT3); //Sat Apr 18 2020 19:29:33 GMT+0300 (GMT+03:00)
let DT4 = new Date(2020, 3, 18, 19, 29, 33); // 3 - Квітень, бо 0 - січень
console.log (DT4); //Sat Apr 18 2020 19:29:33 GMT+0300 (GMT+03:00)
Виклик Date
як функції, тобто без оператора new
, повертає теперішню дату та час як рядок (string).
console.log (Date()); //виведе плинну дату та час
Наступні методи працюють для глобального об’єкту Date
, але не для об’єктів створених за допомогою конструктора Date
.
Таблиця 14.7. Методи об’єкту Date
.
Метод | Опис |
---|---|
Date.now() |
Вертає ціле число, що позначає поточний час — кількість мілісекунд від 00:00:00 за UTC 1 січня 1970 року без врахування високосних секунд. |
Date.parse() |
Розбирає текстовий запис (рядок) із датою (часом) та повертає кількість мілісекунд між 00:00:00 за UTC 1 січня 1970 та зазначеною миттю у часі. Високосні секунди не враховуються. |
Date.UTC() |
Приймає ті самі параметри, що й найдовша форма конструктора (від 2 до 7), та вертає кількість мілісекунд між 00:00:00 1 січня 1970 року за UTC та зазначеною миттю у часі без врахування високосних секунд. |
tsDT1 = Date.now();
console.log (tsDT1); //1587225137339
tsDT2 = Date.parse("2020, 4, 18 19:29:33");
console.log(tsDT2); //1587227373000
tsDT3 = Date.UTC(2020, 3, 18, 19, 29, 33);
console.log (tsDT3); //1587238173000
console.log ((tsDT3-tsDT2)/(60*60*1000));//3 - години різниці
Методи об’єкта Date
для роботи з датами та часом діляться на наступні категорії::
set
методи, для встановлення дати та часу в об’єкт Date
.get
методи, для отримання дати та часу з об’єкту Date
.to
методи, для отримання значення об’єкта Date
в рядковому вигляді.За допомогою методів групи get
та set
можна встановлювати секунди, хвилини, години, дні місяця, дні тижнів, місяці та роки окремо. Слід звернути увагу на метод getDay
, який повертає день тижня, але не існує відповідного методу setDay
, оскільки день тижня встановлюється(вираховується) автоматично. Всі ці методи використовують цілі числа для представлення відповідних даних, як показано нижче:
0
до 9999
0
до 59
0
до 23
0
(Неділя) до 6
(Субота)1
до 31
(день місяця)0
(Січень) до 11
(Грудень)1900
Методи get
наведені в наступній таблиці:
Таблиця 14.8. Методи get об’єкту Date.
Метод | Опис |
---|---|
getFullYear() , getMonth() , getDate() , getDay() , getHours() , getMinutes() , getSeconds() , getMilliseconds() |
отримання відповідно року, місяця, дати, дня тижня, години, хвилини, секунди, мілісекунди |
getTime() |
отримання TimeStamp |
getUTC | те саме що і get тільки для часу UTC |
getTimezoneOffset() |
зміщення в хвилинах місцевої часової зони, що налаштована в пристрої (ПК) відносно UTC |
let DT1 = new Date("2020, 4, 18 19:29:33");
console.log (DT1.getFullYear());//2020
console.log (DT1.getMonth()); //3 - квітень, бо 0 -січень
console.log (DT1.getDate()); //18
console.log (DT1.getDay()); //6 - субота (0 - неділя)
console.log (DT1.getTime()); //1587227373000 - TimeStamp
console.log (DT1.getHours()); //19
console.log (DT1.getMinutes()); //29
console.log (DT1.getSeconds()); //33
console.log (DT1.getTimezoneOffset());//-180 - 3 години до UTC
Методи set
наведені в наступній таблиці
Таблиця 14.9. Методи set об’єкту Date.
Метод | Опис |
---|---|
setFullYear() , setMonth() , setDate() , setHours() , setMinutes() , setSeconds() , setMilliseconds() |
встановлення відповідно року, місяця, дати, години, хвилини, секунди, мілісекунди |
setTime() |
встановлення часу через мілісекунди (TimeStamp) |
Date.prototype.setUTC | те саме що і set але для часу UTC |
let DT1 = new Date(0); console.log (DT1); //Jan 01 1970 03:00:00
DT1.setFullYear (2020);//можна DT1.setFullYear (2020, 3, 18) щоб задати повністю дату
DT1.setMonth(3);//3 - квітень, бо 0-січень;можна DT1.setMonth(3, 18), щоб задати ще і дату
DT1.setDate(18);
DT1.setHours(19);//години, можна DT1.setHours(19,29,33) щоб задати повінстю час
DT1.setMinutes(29);//хвилини, можна DT1.setMinutes(29,33) щоб задати ще хвилини
DT1.setSeconds(33);//секунди, можна DT1.setSeconds(33,500), щоб задати мс
console.log (DT1); //Apr 18 2020 19:29:33
DT1.setTime(1000); //1587227373000 - TimeStamp
console.log (DT1); //Jan 01 1970 03:00:01
Наступні методи перетворюють дату в один з форматів:
Таблиця 14.10. Методи to об’єкту Date.
Метод | Опис |
---|---|
toString() |
перетворює в строкове представлення дати та часу в форматі ECMA-262 |
toDateString() , toTimeString() |
перетворює в строкове представлення відповідно дати та часу в форматі перетворює в строкове представлення дати та часу в форматі ECMA-262 |
toISOString() |
перетворює в строкове представлення дати та часу в форматі ISO 8601 |
toJSON() |
перетворює в строкове представлення дати та часу аналогічно попередньому |
toLocaleString() |
перетворює в строкове представлення дати та часу відповідно до національних налаштувань (задаються в аргументах) |
toLocaleTimeString() , toLocaleDateString() |
перетворює в строкове представлення відповідно дату та час до національних налаштувань (задаються в аргументах) |
toUTCString() |
перетворює в строкове представлення UTC |
valueOf() |
перетворення в примітивний тип, тобто в TimeStamp |
let DT1 = new Date("2020, 4, 18 19:29:33");
console.log (DT1.toString()); //Sat Apr 18 2020 19:29:33 GMT+0300 (GMT+03:00)
console.log (DT1.toDateString()); //Sat Apr 18 2020
console.log (DT1.toTimeString()); //19:29:33 GMT+0300 (GMT+03:00)
console.log (DT1.toLocaleString("en-US")); //4/18/2020, 7:29:33 PM
console.log (DT1.toLocaleString()); //2020-4-18 19:29:33
console.log (DT1.toLocaleDateString());//2020-4-18
console.log (DT1.toLocaleTimeString());//19:29:33
console.log (DT1.toISOString()); //2020-04-18T16:29:33.000Z
console.log (DT1.toUTCString()); //Sat, 18 Apr 2020 16:29:33 GMT
console.log (DT1.toJSON()); //2020-04-18T16:29:33.000Z
console.log (DT1.valueOf()); //1587227373000
Враховуючи, що дата по суті представлена в числовому форматі, з ними можна проводити операції, як з числами.
let DT1 = new Date("2020, 4, 18 19:29:33");
let DT2 = new Date("2019, 4, 18 19:29:33");
console.log (DT2>DT1); //false
console.log (DT2<DT1); //true
console.log (DT1-DT2); //31622400000 мс
console.log ((DT1-DT2)/(24*60*60*1000)); //366 днів
Об’єкт JSON
містить методи розбору (parsing) JavaScript Object Notation (JSON) та навпаки - перетворення значень у JSON. Він не має конструкторів
Таким чином він має всього два методи.
JSON.stringify
для перетворення об’єктів та примітивів в JSON.JSON.parse
для перетворення JSON в об’єкти або примітивиЦі методи JSON працюють з об’єктами, масивами, рядками, числами, булевими значеннями.
Метод JSON.stringify(student)
перетворює об’єкт student
у рядок. Отриманий рядок json
називається JSON-форматованим або серіалізованим об’єктом. Ми можемо відправити його по мережі або помістити у сховище даних (БД).
Об’єкт у форматі JSON має кілька важливих відмінностей від об’єктного літералу:
'John'
перетворюється в "John"
.age:30
стає"age":30
.console.log( JSON.stringify('test') ) // "test" рядок в подвійних лапках
console.log( JSON.stringify([1, 2, 3]) ); // [1,2,3]
let meetup = {
title: "Conference",
room: {number: 23, participants: ["john", "ann"]}
};
console.log ( JSON.stringify(meetup) );
/* вийде рядок:
{"title":"Conference","room":{"number":23,"participants":["john","ann"]}}
*/
JSON є незалежною від мови специфікацією для даних, тому JSON.stringify
пропускає деякі специфічні властивості об’єктів JavaScript, а саме:
undefined
.Однак це обмеження можна обійти через використання replacer
.
Якщо необхідно налаштувати які саме властивості необхідно кодувати та вказати відступи можна використати повний синтаксис JSON.stringify
:
let json = JSON.stringify(value[, replacer, space])
value
- значення для кодування.replacer
- масив властивостей для кодування або функція відповідності function(key, value)
.space
- додатковий простір (відступи), що використовується для форматуванняJSON.parse розбирає (парсить) рядок із JSON, створюючи відповідне до його вмісту значення чи об’єкт. Якщо при виклику в параметрі reviver
(другий необов’язковий параметр) вказати функцію, то її буде використано для перетворення створеного об’єкта та його властивостей перед поверненням.
Синтаксис:
let value = JSON.parse(text[, reviver]);
text
- рядок, що його має бути розібрано, як JSON. Докладні відомості про синтаксис JSON наведено в статті про об’єкт JSON
.
reviver
(не обов’язковий) - якщо вказано функцію, її буде використано для перетворення отриманих значень перед поверненням.
Наприклад:
let txt = "[0, 1, 2, 3]"; //текст, що вміщує масив в форматі JSON
numbers = JSON.parse(txt);
console.log (numbers[1] ); // 1
let txt2 = '{ "name": "John", "age": 35, "isAdmin": false, "friends": [0,1,2,3] }';
user = JSON.parse(txt2);
console.log ( user.friends[1] ); // 1
Параметр reviver
можна використати для керування розбором. Наприклад, необхідно отримати об’єкт meetup
, який передається у вигляді рядку JSON. При цьому об’єкт містить об’єкт Date. При перетворенні в об’єкт, вийде наступний результат:
//на вузлі відправника
let meetupsend= {title:"Conference", date:new Date("2020-11-30T12:00:00.000Z")};
console.log(meetupsend.date.getDate()); //30
let str = JSON.stringify (meetupsend);
console.log (str);//{"title":"Conference","date":"2020-11-30T12:00:00.000Z"}
//на вузлі отримувача
let meetup = JSON.parse(str);
console.log(meetup.date.getDate()); // TypeError: meetup.date.getDate is not a function
Виникає помилка, бо значенням meetup.date
є рядок, а не об’єкт Date
, тому що JSON.parse
не міг знати який саме тип було використано при перетворенні в JSON. У цьому випадку можна скористатися параметром reviver
, який буде викликати функцію для перетворення кожного ключа.
let str = '{"title":"Conference","date":"2020-11-30T12:00:00.000Z"}';
let meetup = JSON.parse(str, function(key, value) {
if (key == 'date') return new Date(value);
return value;
});
console.log( meetup.date.getDate() ); // 30
У JavaScript функції - це також об’єкти, які мають властивості і методи.
let fno = function fn1(a,b,c){console.log (a+b+c);}
console.log (fno.name); //fn1 - ім'я функції
console.log (fno.length); //3 - кількість параметрів
console.log (fno.toString());//повертає першокод функції, вивід буде наступний
//function fn1(a,b,c){console.log (a+b+c);}
fno.call (this, 100,10,1); //111, викликає фукнкцію, this передається для контекста
Буфер - область пам’яті, яка використовується для тимчасового збереження бінарних даних (I/O, файли, мережа …). Для роботи з буфером використовується глобальний клас Buffer, який надає для цього ряд методів.
let buf1 = Buffer.alloc(8,0xFF); // виділити буфер на 8 байт і заповнити
buf1.write('ABC', 2);//записати 65,66,67 с 2-го байта
let buf2 = Buffer.from('DEF'); //отримати буфер з рядку => 68 69 70
let buf3 = Buffer.from([1,2]); //отримати буфер з масиву
let buf4 = Buffer.concat([buf1,buf3,buf2],buf1.length + buf2.length + buf3.length);
console.log (buf4.length); //24
console.log (buf4.toJSON().data);//виведе масив значень байтів буферу
Буфер можна вважати байтовою послідовністю. Для інтерпретації цієї послідовності як даних певного типу, є різноманітні методи, наприклад readInt16BE(offset)
інтерпретує 16-біт буферу починаючи з offset
як 16-бітний Integer в форматі Big Endian
. Ось кілька прикладів:
const buf = Buffer.from([1, 2, 3, 4, 0, 5]);
console.log(buf.readInt16BE(4)); //виведе 5 0x0005
console.log(buf.readInt16LE(4)); //виведе 1280 0x0500
buf.writeFloatBE(36.5, 0); //запише 36.5 в форматі BigEndian
console.log(buf.readFloatBE(0)); //виведе 36.5
console.log(buf.readFloatLE(0)); //виведе 6.549669022254195e-42
Усі методи наведені в документації
Теоретичне заняття розробив Олександр Пупена.