Български
Тема
Български
Тема
Днес ще се научите да:
let и const и да им давате добри имена;typeof;Къде е мястото на тази тема в примерното правило за проверка - днес можем да напишем маркираните редове:
function rule(doc) {
const library = require("library.js");
let name = String(doc.inventory?.extended_info?.json?.data?.system?.name
|| doc.status.device_alias);
let serial = doc.overview.serial_number;
let model = doc.overview.model;
let version = doc.overview.version;
if (["XR-210", "XR-220"].includes(doc.overview.model)
&& !library.version_below(doc.overview.version, "4.2.1.7")) {
emit(doc.status.device_alias, { /* ... alert details ... */ });
}
}Variable е име за стойност в паметта. Създаването ѝ има две части:
let serial;serial = "SN4X7Q92";Обикновено правим двете наведнъж:
let serial; // declared, but has no value yet
console.log(serial); // undefined
serial = "SN4X7Q92"; // now defined
console.log(serial);
let model = "XR-220"; // declared and defined at once
console.log(model);let serial; // declared, but has no value yet
console.log(serial); // undefined
serial = "SN4X7Q92"; // now defined
console.log(serial);
let model = "XR-220"; // declared and defined at once
console.log(model);Анимации
Variables в паметта: 1. Деклариране и присвояване, 2. Копиране на стойност
let и const | Ключова дума | Може ли да получи нова стойност? | За какво се ползва |
|---|---|---|
const | не | стойности, които не се променят - повечето ви variables |
let | да | броячи, резултати, които се натрупват стъпка по стъпка |
var | да | само в стар код - не го използвайте в нов код |
const model = "XR-220";
let checkedSystems = 0;
checkedSystems = checkedSystems + 1; // fine, it is a let
console.log(checkedSystems);
model = "XR-210"; // error: model is a const
console.log("this line never runs");const model = "XR-220";
let checkedSystems = 0;
checkedSystems = checkedSystems + 1; // fine, it is a let
console.log(checkedSystems);
model = "XR-210"; // error: model is a const
console.log("this line never runs");Започвайте с const
Пишете const по подразбиране. Сменете го с let само когато наистина трябва да дадете нова стойност на variable. Добрите насоки за правилата искат същото за глобалните variables: "they must be declared as const".
Анимация
Variables в паметта: 5. const
MDN: Strict mode
Без let, const или var JavaScript тихо създава глобална variable. Тогава печатна грешка в името създава нова variable, вместо да даде грешка:
let firmwareLevel = "4.2.1.7";
firmwarelevel = "4.3.0.0"; // typo: small "l" - a new global variable!
console.log(firmwareLevel); // still 4.2.1.7let firmwareLevel = "4.2.1.7";
firmwarelevel = "4.3.0.0"; // typo: small "l" - a new global variable!
console.log(firmwareLevel); // still 4.2.1.7Сложете "use strict"; като първи ред на файла (или на функцията) и същата грешка вече спира програмата:
"use strict";
let firmwareLevel = "4.2.1.7";
FirmwareLevel = "4.3.0.0"; // typo: capital "F" - now an error
console.log(firmwareLevel);"use strict";
let firmwareLevel = "4.2.1.7";
FirmwareLevel = "4.3.0.0"; // typo: capital "F" - now an error
console.log(firmwareLevel);ИНФОРМАЦИЯ
Модулите и класовете винаги са в strict mode. Във файловете за упражнения започваме с "use strict";.
Анимация
Scope на variables: 4. Без деклариране и "use strict"
Правила (иначе: синтактична грешка):
_ и $; без интервали, без -;let, const, if, function, class, ...);model, MODEL и Model са три различни variables.Конвенции (добра практика):
camelCase за variables: serialNumber, firmwareLevel, isAffected;firmwareLevel, а не x или data2;is, has, can: isEnabled, hasCert;UPPER_SNAKE_CASE за фиксирани настройки: const MIN_FIRMWARE_LEVEL = "4.2.1.7";Ключове в JSON срещу имена на variables
Ключовете в JSON отчета са в snake_case (firmware_level, remote_login_enabled). Така са кръстени данните - оставете ключовете както са. Вашите собствени variables са в camelCase: const firmwareLevel = doc.inventory.details.firmware_level;
Проверете се: кои от тези имена са валидни?
serial_number, 2ndNode, firmware-level, $total, const, isRemote, MODEL
Валидни: serial_number, $total, isRemote, MODEL. Невалидни: 2ndNode (започва с цифра), firmware-level (- е минус), const (запазена дума).
MDN: JavaScript data types and data structures
Една стойност в JavaScript е или примитивна (една проста стойност), или обект (структура с properties - като doc). Примитивните типове:
| Тип | Примери | В данните на отчета |
|---|---|---|
number | 42, 9.1, -3, 1_000_000 | бройки, размери (след преобразуване) |
string | "XR-220", 'yes', `text` | почти всяка стойност |
boolean | true, false | "yes" / "no" след преобразуване |
undefined | undefined | ключ, който го няма в документа |
null | null | "няма стойност", записано нарочно |
(Има още два - bigint и symbol, но рядко трябват.)
typeof MDN: typeof
console.log(typeof 42); // number
console.log(typeof "4.2.1.7"); // string
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object - a famous old bug in JavaScript
console.log(typeof doc); // objectconsole.log(typeof 42); // number
console.log(typeof "4.2.1.7"); // string
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object - a famous old bug in JavaScript
console.log(typeof doc); // objectЦелите и дробните числа са от един и същ тип - number:
const nodes = 2;
const ratio = 0.75;
const capacityBytes = 2_199_023_255_552; // "_" only makes it readable
console.log(nodes, ratio, capacityBytes);
console.log(0.1 + 0.2); // not exactly 0.3!
console.log(10 / 0); // Infinityconst nodes = 2;
const ratio = 0.75;
const capacityBytes = 2_199_023_255_552; // "_" only makes it readable
console.log(nodes, ratio, capacityBytes);
console.log(0.1 + 0.2); // not exactly 0.3!
console.log(10 / 0); // InfinityДробните числа не са точни
0.1 + 0.2 дава 0.30000000000000004. Числата се пазят в двоичен вид, затова повечето дробни числа са приближения. Закръглявайте резултатите, преди да ги покажете.
Анимации
Числата в паметта: 1. Битове и цели числа, 2. Дроби и 0.1, 4. 0.1 + 0.2, 6. NaN и Infinity
MDN: String, Template literals
Три вида кавички:
const a = "double quotes";
const b = 'single quotes';
const c = `backticks: a template string`;
console.log(a);
console.log(b);
console.log(c);const a = "double quotes";
const b = 'single quotes';
const c = `backticks: a template string`;
console.log(a);
console.log(b);
console.log(c);Escape последователности - специални символи в string:
console.log("Name:\tLAB-DEV-01"); // \t tab
console.log("line 1\nline 2"); // \n new line
console.log("the \"Version\" column"); // \" a quote inside a string
console.log("C:\\checks\\rules"); // \\ a backslashconsole.log("Name:\tLAB-DEV-01"); // \t tab
console.log("line 1\nline 2"); // \n new line
console.log("the \"Version\" column"); // \" a quote inside a string
console.log("C:\\checks\\rules"); // \\ a backslashTemplate strings (с обратни кавички) могат да са на няколко реда и вмъкват стойности с ${...} - много удобно за съобщенията на alert:
const name = "LAB-DEV-01";
const model = "XR-220";
const firmwareLevel = "4.2.1.7";
const message = `System ${name} (${model}) runs firmware level ${firmwareLevel}.`;
console.log(message);const name = "LAB-DEV-01";
const model = "XR-220";
const firmwareLevel = "4.2.1.7";
const message = `System ${name} (${model}) runs firmware level ${firmwareLevel}.`;
console.log(message);undefined и null undefined - "тук нищо не е сложено": декларирана variable без стойност или ключ, който го няма в документа.null - "няма стойност", зададено нарочно.console.log(doc.overview.model); // the key exists
console.log(doc.overview.nickname); // no such key: undefinedconsole.log(doc.overview.model); // the key exists
console.log(doc.overview.nickname); // no such key: undefinedЕто защо правилата проверяват за липсващи данни
Четенето на липсващ ключ дава undefined. Четенето на ключ от undefined е грешка - точно от това пази ?. в примерното правило (занятие 6).
Анимация
Variables в паметта: 4. Типове стойности
// a one-line comment
/*
a comment over
several lines
*/
/**
* A documentation comment (JSDoc) - describes the code below it.
* A rule template usually starts with one.
*/Пишете коментари, които обясняват защо, а не какво: // rule guidelines require const globals е полезен; // set x to 5 не е.
= слага стойността отдясно в variable отляво. Кратки форми:
let alerts = 0;
alerts = alerts + 1; // 1
alerts += 2; // same as alerts = alerts + 2 -> 3
alerts -= 1; // 2
alerts *= 10; // 20
alerts++; // add 1 -> 21
alerts--; // subtract 1 -> 20
console.log(alerts);let alerts = 0;
alerts = alerts + 1; // 1
alerts += 2; // same as alerts = alerts + 2 -> 3
alerts -= 1; // 2
alerts *= 10; // 20
alerts++; // add 1 -> 21
alerts--; // subtract 1 -> 20
console.log(alerts);Анимации
Variables в паметта: 3. x = x ** 2
Как се изчислява един израз: 3. Присвояването е израз, 4. i++ и ++i
| Оператор | Значение | Пример | Резултат |
|---|---|---|---|
+ - * / | както в математиката | 7 / 2 | 3.5 |
% | остатък | 7 % 2 | 1 |
** | степен | 2 ** 10 | 1024 |
Пример с дисково пространство - от байтове в TiB (1 TiB = 10244 байта):
const capacityBytes = 2_199_023_255_552;
const usedBytes = 1_517_325_046_333;
const capacityTiB = capacityBytes / 1024 ** 4;
const usedPercent = usedBytes / capacityBytes * 100;
console.log(capacityTiB); // 2
console.log(usedPercent); // many decimals
console.log(Math.round(usedPercent)); // 69
console.log(usedPercent.toFixed(1)); // 69.0 - a string with 1 decimalconst capacityBytes = 2_199_023_255_552;
const usedBytes = 1_517_325_046_333;
const capacityTiB = capacityBytes / 1024 ** 4;
const usedPercent = usedBytes / capacityBytes * 100;
console.log(capacityTiB); // 2
console.log(usedPercent); // many decimals
console.log(Math.round(usedPercent)); // 69
console.log(usedPercent.toFixed(1)); // 69.0 - a string with 1 decimalMDN: Operator precedence
Както в математиката: първо **, после * / %, после + -. Когато се колебаете, слагайте скоби:
console.log(2 + 3 * 4); // 14
console.log((2 + 3) * 4); // 20
console.log(100 - 60 / 2); // 70console.log(2 + 3 * 4); // 14
console.log((2 + 3) * 4); // 20
console.log(100 - 60 / 2); // 70Проверете се: какво извежда 10 + 20 / 10 * 2 ** 2?
18: първо 2 ** 2 = 4, после 20 / 10 = 2, 2 * 4 = 8, после 10 + 8.
Анимации
Как се изчислява един израз: 1. Приоритет, 2. Асоциативност, 5. Ред на изчисляване (advanced)
+ със string съединява (конкатенира). Останалите аритметични оператори превръщат strings в numbers:
console.log("9" + 1); // 91 - joined
console.log("9" - 1); // 8 - subtracted
console.log("3" * "4"); // 12
console.log(1 + 2 + "3"); // 33 - left to right: 3, then "3" + "3"
console.log("1" + 2 + 3); // 123console.log("9" + 1); // 91 - joined
console.log("9" - 1); // 8 - subtracted
console.log("3" * "4"); // 12
console.log(1 + 2 + "3"); // 33 - left to right: 3, then "3" + "3"
console.log("1" + 2 + 3); // 123ВНИМАНИЕ
"9" + 1 е "91", а не 10. Когато стойностите идват от JSON, първо ги преобразувайте, после смятайте.
Анимация
Типове, сравнения и логика: 1. Операторът +
const version = doc.overview.version;
const enabled = doc.inventory.details.remote_login_enabled;
const epoch = doc.status.epoch;
console.log(version, typeof version);
console.log(enabled, typeof enabled);
console.log(epoch, typeof epoch);const version = doc.overview.version;
const enabled = doc.inventory.details.remote_login_enabled;
const epoch = doc.status.epoch;
console.log(version, typeof version);
console.log(enabled, typeof enabled);
console.log(epoch, typeof epoch);MDN: Number() constructor, parseInt(), parseFloat()
console.log(Number("42")); // 42
console.log(Number(" 42 ")); // 42 - spaces around are ignored
console.log(Number("")); // 0 - careful!
console.log(Number("4.2.1.7")); // NaN - Not a Number
console.log(parseInt("4.2.1.7")); // 4 - reads digits until it cannot
console.log(parseFloat("4.2.1.7")); // 4.2
console.log(parseInt("8 nodes")); // 8console.log(Number("42")); // 42
console.log(Number(" 42 ")); // 42 - spaces around are ignored
console.log(Number("")); // 0 - careful!
console.log(Number("4.2.1.7")); // NaN - Not a Number
console.log(parseInt("4.2.1.7")); // 4 - reads digits until it cannot
console.log(parseFloat("4.2.1.7")); // 4.2
console.log(parseInt("8 nodes")); // 8Number(x) - целият string трябва да е число, иначе NaN.parseInt(x) / parseFloat(x) - четат от началото, докъдето могат.NaN е number, който означава "невалидно число". Проверявайте го с Number.isNaN(value).Версията не е число
"4.2.1.7" има четири части. Number дава NaN, parseFloat дава 4.2 - и двете губят информация. Ще сравняваме версии част по част в занятие 5.
Анимация
Типове, сравнения и логика: 2. От string към number
const nodes = 2;
console.log(String(nodes)); // 2 (a string)
console.log(nodes + ""); // 2 (a string)
console.log(`${nodes}`); // 2 (a string)
console.log(typeof String(nodes)); // stringconst nodes = 2;
console.log(String(nodes)); // 2 (a string)
console.log(nodes + ""); // 2 (a string)
console.log(`${nodes}`); // 2 (a string)
console.log(typeof String(nodes)); // stringПримерното правило обвива името в String(...), така че резултатът винаги е string, каквото и да съдържа JSON.
Сравнявайте с текста, който очаквате - === означава "точно равно на" (повече в занятие 3):
const enabledText = doc.inventory.details.remote_login_enabled; // "yes"
const isEnabled = enabledText === "yes";
console.log(isEnabled); // true
console.log(typeof isEnabled); // booleanconst enabledText = doc.inventory.details.remote_login_enabled; // "yes"
const isEnabled = enabledText === "yes";
console.log(isEnabled); // true
console.log(typeof isEnabled); // booleanEPOCH в отчета е броят секунди от 1 януари 1970 г. (UTC), записан като string. Датите в JavaScript броят милисекунди:
const epochSeconds = Number(doc.status.epoch);
const reportDate = new Date(epochSeconds * 1000);
console.log(epochSeconds);
console.log(reportDate.toISOString());const epochSeconds = Number(doc.status.epoch);
const reportDate = new Date(epochSeconds * 1000);
console.log(epochSeconds);
console.log(reportDate.toISOString());Отворете във VSCode вашето копие на Homework repository (първия път: вижте Как да ползвате тези страници; преди занятието: git pull --no-rebase --no-edit upstream main) и пускайте задачите от терминала, в основната папка на repository-то:
node 02-variables-and-types/practice/task1-rule-variables.jsВсеки файл обяснява задачата в началото си. Пишете кода си между редовете your code; проверките най-долу извеждат OK или FAIL.
| Задача | Файл | Какво правите |
|---|---|---|
| 1 | task1-rule-variables.js | Variables за данните на примерното правило и съобщение за alert с template string |
| 2 | task2-predict-types.js | Предвидете резултата от 12 израза, после проверете |
| 3 | task3-capacity.js | Байтове от JSON (strings) в TiB и процент заето място |
| 4 | task4-report-age.js | Преди колко дни и часа е изпратен един отчет |
| Тема | Запомнете |
|---|---|
| Variables | const по подразбиране, let, когато стойността се променя, никога var; "use strict"; |
| Имена | camelCase, със смисъл; ключовете в JSON остават каквито са |
| Типове | number, string, boolean, undefined, null; проверка с typeof |
| Strings | "...", '...', `...${value}...`; escape последователности \n, \t, \" |
| Оператори | + - * / % **, +=, ++; приоритет като в математиката |
+ със strings | съединява: "9" + 1 е "91" |
| Преобразуване | Number(), parseInt(), parseFloat(), String(); NaN; === "yes" |
02-variables-and-types/homework.js (в homework repository): обобщение за отдалечения вход от стойностите remote_login_*.OK.Следващото занятие: сравнения, логически оператори, условия и loops - и if от примерното правило.