MakeFirstStep· Frontend + зеҳни сунъӣ

Дарси 20 · Абзорҳо ва марҳалаи ниҳоӣ

Коди тоза, рефакторинг ва деплой

Кодро як бор менависанд, ва даҳҳо бор мехонанд. Пас аз як моҳ шумо худатон намефаҳмед, ки дар x2 чиро дар назар доштед, ва корфармо дар мусоҳиба репозиторийи шуморо дар 30 сония мекушояд. Имрӯз ёд мегирем, ки кодро ба тартиб оварем, то он вайрон нашавад, ва баъд лоиҳаҳоро ба интернет мегузорем — то тавассути истинод ҳар кас, аз модар то рекрутер, онҳоро кушода тавонад.

  • Ба тағйирёбандаҳо ва функсияҳо номҳое додан, ки шарҳ додани онҳо лозим нест
  • Функсияҳои калонро тақсим кардан, ҷойгиршавии дарунро бо return-и барвақтӣ бартараф намудан, такрор накардан (DRY)
  • «Рақамҳои ҷодуӣ»-ро ба собитҳо баровардан ва ҳисобҳоро аз намоиш ҷудо кардан
  • Кодро аз рӯи чек-лист санҷидан ва рефакторинг кардан, то рафтор тағйир наёбад
  • Лоиҳаро бо фармони npm run build ҷамъ кардан ва тағйирёбандаҳои муҳитро бе ошкор шудани сирҳо танзим намудан
  • Лоиҳаро дар Vercel ва GitHub Pages деплой кардан, ва маслиҳатҳои ревьюи ЗС-ро ба фоиданок ва зарарнок ҷудо намудан
Бо ин саҳифа чӣ тавр кор кардан лозим

Коди бо тугмаи ▶ Иҷро кардан — зинда аст: онро тағйир диҳед ва натиҷаро дар консол бинед. Блокҳо бо имзои «Терминал» ва файлҳои танзимотиро иҷро кардан мумкин нест — онҳоро дар компютери худ такрор мекунед. Дар вазифаҳои рефакторинг рафтори код тағйир додан мумкин нест: санҷиш баромадро муқоиса мекунад, барои ҳамин дар ҳар чунин вазифа дар поён аллакай сатрҳои-тест ҳастанд. Ба онҳо даст назанед — онҳо суғуртаи шумоянд. Ишораҳо пинҳонанд: аввал худатон.

01 Номҳо: кодро аз навиштан бештар мехонанд

Барои компютер фарқ надорад, ки тағйирёбандаро чӣ ном гузорем: a, x2 ё somoniForOnePlov. Аммо барномаро на танҳо компютер мехонад — онро шумо баъди як ҳафта, ҳамкори лоиҳа ва ёрдамчии ЗС мехонанд. Номи хуб аз шарҳ халос мекунад: аз он фавран фаҳмост, ки ин чист ва барои чӣ.

Бояд ҳал карда шавад
JavaScript
const d = 7;
const l = [5, 35, 15];
function proc(x) {
  return x * 11;
}
let flag = false;
Мисли матн хонда мешавад
JavaScript
const daysInWeek = 7;
const dishPrices = [5, 35, 15];
function convertUsdToSomoni(usd) {
  return usd * 11;
}
let isPaid = false;
Монандӣ аз ҳаёт

Ошхонаи чойхонаро тасаввур кунед, ки дар он ҳамаи шишаҳо бо «Шиша 1», «Шиша 2», «Шиша 3» имзо шудаанд. Ошпази навкор ба палав на зира, балки гичи сурхро мегузорад. Акнун шишаҳо бо навишти «Зира», «Намак», «Зирк» — хато кардан қариб ғайриимкон аст. Номҳои тағйирёбандаҳо — ин имзоҳо дар шишаҳои барномаи шумост.

Қоидаҳои номҳои хуб

Чиро ном мегузоремЧӣ таврМисол
Тағйирёбанда бо маълумотисм, мазмунро тавсиф мекунадstudentName, totalPrice
Массивисм дар шакли ҷамъstudents, prices
Функсияфеъл + чӣ кор мекунадcalcTotal, renderMenu, getUserName
Қимати булӣсавол: is, has, canisPaid, hasTicket, canEnroll
СобитБО ҲАРФҲОИ КАЛОН тавассути зерхатMAX_TRIES, USD_RATE
  • Бе ихтисорҳо, ки танҳо шумо медонед: cnt, usr, tmp. Панҷ ҳарфи зиёдатӣ — нархи арзон барои возеҳӣ. Истисно — маъмулан қабулшудаҳо: i дар давраи кӯтоҳ, id, url.
  • Бе калимаҳои «партов»: data, info, temp, thing, list2. Аз худ бипурсед: «Кадом маълумот дақиқан?»
  • Як калима — як мафҳум. Агар дар як ҷо getUser, дар ҷои дигар fetchOrder, ва дар сеюм loadProduct бошад — барои як навъи амал як феълро интихоб кунед ва ба он вафодор бошед.
  • Дарозии ном аз «умр»-и тағйирёбанда вобаста аст. Тағйирёбанда барои се сатр метавонад кӯтоҳ бошад (item), ва барои тамоми файл намоён — муфассал (selectedDishId).
  • Танҳо лотинӣ, забон — англисӣ. Шарҳҳо ва матнҳо барои корбарро бо тоҷикӣ менависем.
Бадтарин чиз: ном дурӯғ мегӯяд

Функсияи getUser, ки дар баробар корбарро хориҷ мекунад. Тағйирёбандаи isEmpty, ки вақте рӯйхат холӣ нест, ба true баробар аст. Чунин код аз коди бо номҳои бад хатарноктар аст: шумо ба ном такя мекунед — ва хато мекунед. Агар рафторро тағйир додед — номро ҳам тағйир диҳед.

Ном дурӯғ мегӯяд — ва код баръакс хонда мешавад · Ctrl + Enter
const items = [5, 35];
const isEmpty = items.length > 0;   // ✖ дар асл «холӣ нест»

if (isEmpty) {
  console.log("Корзина пуста");     // ← аммо сабад ҳамоно пур аст!
}

Муфассалтар хонед: learn.javascript.ru — Услуби код, learn.javascript.ru — Коди ниндзя (чӣ тавр набояд кард)

Амал: мустаҳкам мекунем

Ёд мегирем, ки номҳои бадро пай барем ва ислоҳ кунем.

ВАЗИФАИ 1.1

Номи хуб ё бад

осон

Дар зер ҳашт порча. Ба массиви badNames рақамҳои онҳоеро нависед, ки номашон бад аст (нофаҳмо, партов ё намегӯяд, ки дар дохил чӣ ҳаст). Рақамҳо — бо тартиби афзоиш. Онҳоро бо вергул чоп кунед.

Таҳрир кардан мумкин аст · Ctrl + Enter
// 1
const d = 7;
// 2
const daysInWeek = 7;
// 3
function proc(x) { return x * 2; }
// 4
const isPaid = true;
// 5
const flag = false;   // дар ин ҷо «оё фармоиш пардохт шудааст» нигоҳ дошта мешавад
// 6
const students = ["Рустам", "Нилуфар"];
// 7
function getStudentCount(students) { return students.length; }
// 8
const data2 = [1, 2, 3];

const badNames = [/* рақамҳои номҳои бад */];
console.log(badNames.join(", "));
Натиҷаи интизоршаванда
1, 3, 5, 8
Ишора 1

Барои ҳар ном бипурсед: «Агар онро пас аз як моҳ бубинам — мефаҳмам, ки ин чист?» Як ҳарф, proc, flag, data2 — чизе нахоҳанд гуфт.

Ишора 2

Номҳои хуб дар ин ҷо бо рақамҳои 2, 4, 6 ва 7 мебошанд. Чаҳор боқимонда — ҷавоби шумост.

ВАЗИФАИ 1.2

Се ҳарф ба ҷои маъно

осон

Тағйирёбандаҳои p, n, t-ро бояд иваз кард: price (нархи як самбӯса), count (чанд дона), total (маблағ). Сатри охирин аллакай номҳои навро истифода мебарад — барои ҳамин ҳоло код меафтад. Рафтор тағйир намеёбад.

Таҳрир кардан мумкин аст · Ctrl + Enter
const p = 25;
const n = 4;
const t = p * n;

console.log(`${price} × ${count} = ${total}`);
Натиҷаи интизоршаванда
25 × 4 = 100
Ишора 1

Ҳар тағйирёбандаро ҳама ҷо, ки вомехӯрад, иваз кунед — ҳам дар эълон, ҳам дар ҳисоби p * n.

Ишора 2

Дар VS Code тугмаи F2 дар номи тағйирёбанда онро фавран дар тамоми файл иваз мекунад. Аммо дар ин машқ бо даст нависед.

ВАЗИФАИ 1.3

Функсияҳои гӯянда

миёна

Се функсия кор мекунанд, аммо чунон номгузорӣ шудаанд, ки чизе фаҳмида намешавад. Онҳоро ба isAdult, getTotal, formatPrice иваз кунед, ва дар баробар ба параметрҳо ва тағйирёбандаҳо дар дохил номҳои фаҳмо диҳед (age, prices, total, amount). Даъватҳо дар поён аллакай номҳои навро истифода мебаранд. Натиҷа тағйир намеёбад.

Таҳрир кардан мумкин аст · Ctrl + Enter
function check(a) {
  return a >= 18;
}

function calc(arr) {
  let s = 0;
  for (const x of arr) {
    s += x;
  }
  return s;
}

function fmt(n) {
  return n + " сомони";
}

console.log(isAdult(20), isAdult(15));
console.log(getTotal([5, 35, 15]));
console.log(formatPrice(getTotal([5, 35, 15])));
Натиҷаи интизоршаванда
true false
55
55 сомони
Ишора 1

Номи функсия — феъл: getTotal «ҷамъбаст мегирад», formatPrice «нархро формат мекунад». isAdult-и булӣ ба савол «калонсол?» ҷавоб медиҳад.

Ишора 2

Дар давраи for (const x of arr) x-ро бо price ва arr-ро бо prices иваз кунед: ҳамин тавр давра қариб мисли ҷумла хонда мешавад.

02 Функсияҳои хурд ва бозгашти барвақтӣ

Қоидаи рақами як барои функсияҳо: як функсия — як вазифа. Агар шумо онро бо калимаи «ва» тавсиф кунед («маблағро ҳисоб мекунад ва тахфиф татбиқ мекунад ва чек чоп мекунад»), ин се функсия аст. Функсияи кӯтоҳро хондан, ном додан, санҷидан ва дар ҷои дигар истифода бурдан осонтар аст.

  • Андоза. Нишондиҳанда — дар як экран ҷо мешавад, 10–20 сатр. На қонун, балки сигнал: агар варақ мезанед — вақти тақсим кардан расидааст.
  • Параметрҳо. Ду–се — муқаррарӣ. Панҷ ва зиёд — сабаби андеша, ки оё объект додан лозим нест.
  • Як сатҳи тафсилот. Функсияи боло нақл мекунад «чӣ рӯй дода истодааст» (validate → calc → render), ва тафсилот дар функсияҳои хурд пинҳонанд.
Функсияи калон ҳама чизро якбора мекунад · Ctrl + Enter
function processOrder(prices) {
  let sum = 0;
  for (const price of prices) {
    sum += price;
  }
  const discount = sum >= 100 ? sum / 10 : 0;
  console.log("К оплате: " + (sum - discount));
}

processOrder([40, 70, 20]);
Се функсияи хурд — «асосӣ» мисли нақша хонда мешавад · Ctrl + Enter
function calcSum(prices) {
  let sum = 0;
  for (const price of prices) {
    sum += price;
  }
  return sum;
}

function calcDiscount(sum) {
  return sum >= 100 ? sum / 10 : 0;
}

function processOrder(prices) {
  const sum = calcSum(prices);
  const discount = calcDiscount(sum);
  console.log("К оплате: " + (sum - discount));
}

processOrder([40, 70, 20]);

Бозгашти барвақтӣ (guard clauses)

Вақте санҷишҳо ба дохили якдигар ҷойгир мешаванд, «тир»-и қавсҳо ҳосил мешавад: мантиқи асосӣ ба тарафи рост се сатҳ рафт, ва дар сар ҳамаи шартҳоро якбора нигоҳ доштан лозим меояд. Дору — бозгашти барвақтӣ: аввал ҳолатҳои бадро мебуранд ва фавран аз функсия мебароянд, ва мантиқи асосӣ дар як сатҳ мемонад.

Тир аз if-ҳои дарунҷойгир
JavaScript
function getFare(age, hasCard) {
  if (age >= 0) {
    if (hasCard) {
      if (age < 7) {
        return 0;
      } else {
        return 3;
      }
    } else {
      return 5;
    }
  } else {
    return -1;
  }
}
Бозгашти барвақтӣ — ҳамвор
JavaScript
function getFare(age, hasCard) {
  if (age < 0) return -1;
  if (!hasCard) return 5;
  if (age < 7) return 0;
  return 3;
}

Ҳарду функсия як чизро бармегардонанд, аммо дуюмро аз боло ба поён мисли рӯйхати қоидаҳо мехонед. Пай бурдед? Калимаи else нест шуд: пас аз return он лозим нест, функсия аллакай тамом шудааст.

Монандӣ аз ҳаёт

Назоратчӣ дар даромадгоҳи метро чиптаро фавран дар турникет месанҷад ва бе он намегузорад. Тасаввур кунед, ки шуморо дохил карданд, то истгоҳи охир бурданд — ва танҳо дар он ҷо гуфтанд, ки чипта набуд. Бозгашти барвақтӣ — ин турникет дар аввали функсия аст.

Хатои маъмул: дар «посбонӣ» return-ро фаромӯш карданд

Агар дар санҷиш танҳо паём нависед ва return-ро фаромӯш кунед — функсия бо маълумоти бад кор карданро давом медиҳад.

Санҷиш ҳаст, аммо баромад нест · Ctrl + Enter
function divide(a, b) {
  if (b === 0) {
    console.log("Делить на ноль нельзя");   // хабар додем, аммо набаромадем!
  }
  return a / b;                             // ба ҳар ҳол тақсим мекунем
}

console.log(divide(10, 0));   // → Infinity, аммо мехостем қатъ шавем

Муфассалтар хонед: learn.javascript.ru — Функсияҳо, refactoring.guru — Рефакторинг

Амал: мустаҳкам мекунем

Ёд мегирем, ки функсияҳоро тақсим кунем ва дарунҷойгириро бартараф намоем. Рафтори функсияҳо яксон мемонад.

ВАЗИФАИ 2.1

Посбон дар даромадгоҳи толор

миёна

Функсияро бо бозгаштҳои барвақтӣ бознависед: бе ягон else. Ҷавобҳо барои ҳамаи вурудҳо бояд ҳамон хел бимонанд. Сатри охирин месанҷад, ки калимаи else дар матни функсия намондааст (дар шарҳҳо ҳам онро нанависед).

Таҳрир кардан мумкин аст · Ctrl + Enter
function getAccessMessage(age, hasTicket, isVip) {
  if (age >= 18) {
    if (hasTicket) {
      if (isVip) {
        return "Добро пожаловать в VIP-зал";
      } else {
        return "Добро пожаловать в зал";
      }
    } else {
      return "Купите билет";
    }
  } else {
    return "Только с 18 лет";
  }
}

console.log(getAccessMessage(20, true, true));
console.log(getAccessMessage(20, true, false));
console.log(getAccessMessage(20, false, true));
console.log(getAccessMessage(15, true, true));
console.log(getAccessMessage.toString().includes("else"));
Натиҷаи интизоршаванда
Добро пожаловать в VIP-зал
Добро пожаловать в зал
Купите билет
Только с 18 лет
false
Ишора 1

Аз ҳолатҳои «бад» оғоз кунед: if (age < 18) return "Только с 18 лет";. Санҷишҳо бо ҳамон тартибе меоянд, ки дарунҷойгирӣ дар аслӣ.

Ишора 2

Се сатри посбон мемонад: синну сол → чипта → VIP. return-и охирин — барои меҳмони оддӣ «ба толор».

ВАЗИФАИ 2.2

Чек аз тӯда ба се функсия

миёна

printReceipt-ро ба calcSum(prices) (маҷмӯъро бармегардонад), calcDiscount(sum) (тахфифи 10% аз 100 сомонӣ ва боло, вагарна 0) ва худи printReceipt тақсим кунед, ки танҳо онҳоро даъват мекунад ва чоп менамояд. Баромади чек бояд ҳамон хел бимонад.

Таҳрир кардан мумкин аст · Ctrl + Enter
function printReceipt(prices) {
  let sum = 0;
  for (const price of prices) {
    sum += price;
  }
  let discount = 0;
  if (sum >= 100) {
    discount = sum * 0.1;
  }
  const total = sum - discount;
  console.log("Сумма: " + sum);
  console.log("Скидка: " + discount);
  console.log("Итого: " + total);
}

printReceipt([40, 70, 20]);
printReceipt([30, 20]);

console.log(calcSum([10, 20, 30]));
console.log(calcDiscount(200));
console.log(calcDiscount(50));
Натиҷаи интизоршаванда
Сумма: 130
Скидка: 13
Итого: 117
Сумма: 50
Скидка: 0
Итого: 50
60
20
0
Ишора 1

Давраи ҷамъкуниро ба calcSum бо return sum бароред. Шарти тахфифро — ба calcDiscount: он маҷмӯъро мегирад ва рақам бармегардонад.

Ишора 2

Дар дохили printReceipt мемонад: ду даъват (const sum = calcSum(prices), const discount = calcDiscount(sum)), ҳисоби total ва се console.log.

ВАЗИФАИ 2.3

Посбон бе баромад

осон

Функсияи divide бояд ҳангоми тақсим ба сифр паём чоп кунад ва null-ро баргардонад, на ин ки минбаъд ҳисоб кунад. Ёбед, чӣ намерасад.

Таҳрир кардан мумкин аст · Ctrl + Enter
function divide(a, b) {
  if (b === 0) {
    console.log("Делить на ноль нельзя");
  }
  return a / b;
}

console.log(divide(10, 0));
console.log(divide(10, 2));
Натиҷаи интизоршаванда
Делить на ноль нельзя
null
5
Ишора 1

Паём чоп шуд, аммо функсия тамом нашуд: сатри навбатии return a / b ба ҳар ҳол иҷро мешавад.

Ишора 2

Ба дохили блоки if пас аз console.log сатри return null;-ро илова кунед.

ВАЗИФАИ 2.4

Нархи чипта дар маршрутка

миёна

Функсия нархи сафарро бо сомонӣ ҳисоб мекунад: синну сол берун аз доираи 0–120 → -1; кӯдакон то 7 сола → 0; донишҷӯён → 2; дар рӯзҳои истироҳат → 4; вагарна 5. Онро бе else ва бе тағйирёбандаи price — танҳо бо return-ҳои барвақтӣ бознависед. Натиҷаҳо тағйир намеёбанд.

Таҳрир кардан мумкин аст · Ctrl + Enter
function getTicketPrice(age, isStudent, isWeekend) {
  let price;
  if (age < 0 || age > 120) {
    price = -1;
  } else {
    if (age < 7) {
      price = 0;
    } else {
      if (isStudent) {
        price = 2;
      } else {
        if (isWeekend) {
          price = 4;
        } else {
          price = 5;
        }
      }
    }
  }
  return price;
}

console.log(getTicketPrice(5, false, false));
console.log(getTicketPrice(20, true, false));
console.log(getTicketPrice(30, false, true));
console.log(getTicketPrice(30, false, false));
console.log(getTicketPrice(-3, false, false));
console.log(getTicketPrice(200, true, true));
console.log(getTicketPrice.toString().includes("else"));
Натиҷаи интизоршаванда
0
2
4
5
-1
-1
false
Ишора 1

Тартиби санҷишҳо муҳим аст: аввал «синну соли ғайриимкон», баъд кӯдакон, баъд донишҷӯён, баъд рӯзҳои истироҳат. Ҳар кадом — як сатри if (...) return ...;.

Ишора 2

Сатри охирини функсия — танҳо return 5; барои ҳамаи ҳолатҳои боқимонда.

03 DRY ва рақамҳои ҷодуӣ

DRY — Don't Repeat Yourself, «такрор накун». Порчаи кодро се бор нусха кардед — яъне ҳангоми ҳар ислоҳ бояд ҳар се нусхаро ёфта, ислоҳ кард. Яктоашро фаромӯш кунед — хатоеро мегиред, ки «гоҳ-гоҳ» зоҳир мешавад. Ҳал ҳамон аст, ки дар дарс дар бораи функсияҳо: як ҷое, ки навишта шудааст, ва бисёр ҷойҳое, ки даъват шудаанд.

Копипаст: формат тағйир ёбад — дар се ҷо ислоҳ кардан лозим · Ctrl + Enter
console.log("Самбуса: " + 5 + " сомони");
console.log("Курутоб: " + 35 + " сомони");
console.log("Шакароб: " + 15 + " сомони");
DRY: формат як бор тасвир шудааст · Ctrl + Enter
function printPriceTag(name, price) {
  console.log(`${name}: ${price} сомони`);
}

const menu = [
  { name: "Самбуса", price: 5 },
  { name: "Курутоб", price: 35 },
  { name: "Шакароб", price: 15 },
];

for (const dish of menu) {
  printPriceTag(dish.name, dish.price);
}
Қоидаи се

Бори дуюм такрор шуд — сабр кунед. Бори сеюм такрор шуд — ба функсия ё маълумот бароред. Аз ҳад зуд абстраксия накунед: ду порчаи монанди код гоҳо тасодуфан монанданд ва пагоҳ фарқ хоҳанд кард. Агар функсияи «умумӣ» бо параметрҳо-парчамҳо (isStudent, isSenior, isSpecial…) пур шавад, шумо чизеро муттаҳид кардед, ки муттаҳид кардан намебоист.

Рақамҳои ҷодуӣ

Рақами ҷодуӣ — рақам (ё сатр) дар код, ки маънояш бе шарҳ нофаҳмо аст. * 11 чӣ маъно дорад? >= 300 чӣ? Пас аз як моҳ худатон ба ёд намеоред. Дору — собити номдор: қиматро ба боло аз файл баровардан ва ба он ном додан.

Ҷодуӣ
JavaScript
function deliveryCost(sum) {
  if (sum >= 300) return 0;
  return 25;
}
Собитҳо маъноро шарҳ медиҳанд
JavaScript
const FREE_DELIVERY_FROM = 300; // сомонӣ
const DELIVERY_PRICE = 25;      // сомонӣ

function deliveryCost(sum) {
  if (sum >= FREE_DELIVERY_FROM) return 0;
  return DELIVERY_PRICE;
}
  • Собитҳоро БО_ҲАРФҲОИ_КАЛОН_ВА_ЗЕРХАТ менависем ва дар аввали файл ҷамъ мекунем — ҳамин тавр ҳамаи «танзимот»-и барнома намоён аст.
  • Воҳиди ченакро ба ном ё шарҳ: TIMEOUT_MS, FREE_DELIVERY_FROM // сомонӣ.
  • Лозим шуд қурб ё остонаро тағйир диҳед — дар як ҷо тағйир медиҳед.
  • Ҷодуӣ нест: 0, 1, -1, 2 дар ҷойҳои возеҳ (i % 2, list.length - 1). Баровардани онҳо — аз ҳад зиёд.
  • Сатрҳо-статусҳо низ ҷодуянд: ба ҷои "paid" дар даҳ ҷо const STATUS_PAID = "paid"-ро эълон кунед — хатои имлоӣ дар номи собит фавран гирифта мешавад, дар сатр — ҳаргиз.
Монандӣ аз ҳаёт

Дар бозор лавҳаи «Қурби доллар — 11 сомонӣ» як дона овезон аст. Агар фурӯшанда ба ҳар харидор қурбро аз нав «аз ёд» эълон мекард, дар як лаҳза яке 11 мегуфт, ва дигаре — 10,5. Собит — ин лавҳаест, ки ҳама ба он менигаранд.

Муфассалтар хонед: refactoring.guru — Иваз кардани рақами ҷодуӣ бо собит

Амал: мустаҳкам мекунем

Рақамҳоро ба собитҳо мебарорем ва копипастро бартараф мекунем. Натиҷаҳо яксон мемонанд.

ВАЗИФАИ 3.1

Қурб ва интиқол

осон

Рақамҳоро ба собитҳо бо номҳои дақиқ бароред: USD_RATE (қурб), FREE_DELIVERY_FROM (остонаи интиқоли ройгон), DELIVERY_PRICE (нархи интиқол). Онҳоро болои функсияҳо эълон кунед. Сатри охирин месанҷад, ки собитҳо вуҷуд доранд.

Таҳрир кардан мумкин аст · Ctrl + Enter
function priceInSomoni(usd) {
  return usd * 11;
}

function deliveryCost(sum) {
  if (sum >= 300) return 0;
  return 25;
}

console.log(priceInSomoni(10));
console.log(deliveryCost(100));
console.log(deliveryCost(300));
console.log(typeof USD_RATE, typeof FREE_DELIVERY_FROM, typeof DELIVERY_PRICE);
Натиҷаи интизоршаванда
110
25
0
number number number
Ишора 1

Се сатри const ... = рақам; дар боло, пеш аз функсияҳо. Номҳо — айнан чунон ки дар шарт.

Ишора 2

Дар дохили функсияҳо рақамҳоро бо номҳо иваз кунед: usd * USD_RATE, sum >= FREE_DELIVERY_FROM, return DELIVERY_PRICE.

ВАЗИФАИ 3.2

Нархномаҳо бе копипаст

миёна

Се блоки баромади нархнома бо ААМ (НДС) танҳо бо ном ва нарх фарқ мекунанд. Онҳоро бо функсияи printPriceTag(name, price) иваз кунед ва онро дар давра аз рӯи массиви menu даъват намоед. Коэффисиенти ААМ — собити VAT_RATE (1.1). Баромад яксон мемонад.

Таҳрир кардан мумкин аст · Ctrl + Enter
const menu = [
  { name: "Самбуса", price: 5 },
  { name: "Курутоб", price: 35 },
  { name: "Шакароб", price: 15 },
];

const samsaPrice = 5;
console.log("Самбуса: " + samsaPrice + " сомони, с НДС " + (samsaPrice * 1.1).toFixed(2));
const kurutobPrice = 35;
console.log("Курутоб: " + kurutobPrice + " сомони, с НДС " + (kurutobPrice * 1.1).toFixed(2));
const shakarobPrice = 15;
console.log("Шакароб: " + shakarobPrice + " сомони, с НДС " + (shakarobPrice * 1.1).toFixed(2));

console.log(printPriceTag.length, typeof VAT_RATE);
Натиҷаи интизоршаванда
Самбуса: 5 сомони, с НДС 5.50
Курутоб: 35 сомони, с НДС 38.50
Шакароб: 15 сомони, с НДС 16.50
2 number
Ишора 1

Функсия ду параметр мегирад ва як сатр чоп мекунад. Се тағйирёбандаи алоҳида бо нархҳо дигар лозим нестанд — маълумот аллакай дар menu аст.

Ишора 2

Давра: for (const dish of menu) { printPriceTag(dish.name, dish.price); }. Сатрро бо қолаб ҷамъ кунед: `${name}: ${price} сомони, с НДС ${(price * VAT_RATE).toFixed(2)}`.

ВАЗИФАИ 3.3

Се тахфиф — як функсия

душвор

Се функсияи тахфиф — нусхаи якдигаранд. Як функсияи умумии applyDiscount(price, percent)-ро созед (натиҷа бо Math.round мудаввар мешавад). Се функсияи кӯҳнаро гузоред — аммо ҳар кадом акнун бояд як сатр бо даъвати умумӣ бошад. Фоизҳоро ба собитҳои STUDENT_DISCOUNT (20), SENIOR_DISCOUNT (30), CHILD_DISCOUNT (50) бароред.

Таҳрир кардан мумкин аст · Ctrl + Enter
function studentPrice(price) {
  const result = price - price * 20 / 100;
  return Math.round(result);
}

function seniorPrice(price) {
  const result = price - price * 30 / 100;
  return Math.round(result);
}

function childPrice(price) {
  const result = price - price * 50 / 100;
  return Math.round(result);
}

console.log(studentPrice(55), seniorPrice(55), childPrice(55));
console.log(applyDiscount(200, 25));
console.log(typeof STUDENT_DISCOUNT, typeof SENIOR_DISCOUNT, typeof CHILD_DISCOUNT);
Натиҷаи интизоршаванда
44 39 28
150
number number number
Ишора 1

Қисми умумии ҳар се: price - price * percent / 100 ва мудаввар кардан. Танҳо фоиз тағйир меёбад — он параметр мешавад.

Ишора 2

Натиҷа: function studentPrice(price) { return applyDiscount(price, STUDENT_DISCOUNT); } — ва ҳамин тавр барои ду боқимонда.

04 Мантиқ ҷудо аз намоиш. Шарҳҳо

Дар ҳар барнома ду кори гуногун ҳаст: ҳисоб кардан (мантиқ: маҳсулотро филтр кардан, холи миёнаро ҳисоб кардан) ва нишон додан (намоиш: HTML ҷамъ кардан, ба консол баровардан). Вақте онҳо дар як функсия ҷамъ шудаанд, онро бе браузер санҷидан намешавад, аз нав истифода бурдан намешавад ва тағйир додан тарсовар аст: ба тарҳ даст занед — математикаро вайрон мекунед.

Монандӣ аз ҳаёт

Ошпаз ва пешхизмат. Ошпаз таомро тайёр мекунад — ин мантиқ аст. Пешхизмат зебо пешкаш мекунад — намоиш. Агар ошпаз худаш ба толор мебаромад, ва пешхизмат ба ошхона барои омехта кардани палав медавид, тағйири оро додани толор ошхонаро суст мекард. Бигзор ҳар кас кори худро кунад ва таоми тайёрро ба якдигар диҳанд — маълумот.

Схема: се нақш

  1. Функсияи ҳисобкунӣ (getAffordableDishes, calcStats): маълумот мегирад, маълумот бармегардонад. Ба DOM даст намезанад, чоп намекунад, тағйирёбандаҳои берунро тағйир намедиҳад. Онро тавассути console.log осон санҷидан мумкин аст.
  2. Функсияи намоиш (renderMenu, formatStats): маълумоти тайёр мегирад, сатр ё унсурҳо месозад. Чизе ҳисоб намекунад.
  3. «Пайвандак» (коркунандаи ҳодиса, функсияи асосӣ): якумро даъват мекунад, натиҷаро ба дуюм медиҳад.
Омехта: ҳисоб ва баромад дар як функсия · Ctrl + Enter
function showStats(grades) {
  let sum = 0;
  for (const grade of grades) sum += grade;
  console.log("Средний балл: " + sum / grades.length);
}

showStats([90, 55, 72]);
Ҷудо: ҳисоб мекунем, баъд нишон медиҳем · Ctrl + Enter
function calcAverage(grades) {
  let sum = 0;
  for (const grade of grades) sum += grade;
  return sum / grades.length;
}

function formatAverage(average) {
  return "Средний балл: " + average;
}

console.log(formatAverage(calcAverage([90, 55, 72])));
console.log(calcAverage([100, 50]));  // ҳисобро алоҳида санҷидан осон аст

Дар дарсҳо дар бораи DOM ва ҳодисаҳо шумо render() месохтед — ин маҳз ҳамон аст. Қоида дуртар меравад: дар React (дарсҳои 22–24) компонент маълумот мегирад ва онро тасвир мекунад, ва ҳисобҳо алоҳида зиндагӣ мекунанд.

Шарҳҳо: «барои чӣ»-ро шарҳ диҳед, на «чӣ»-ро

Он ки код чӣ кор мекунад, аз худи код намоён аст — агар номҳо хубанд. Аммо барои чӣ он чунин навишта шудааст, аз код ҳеҷ намоён нест. Маҳз ин ҷойи шарҳ аст: қоидаи тиҷоратӣ, роҳи гардиш, маҳдудияти ғайриоддӣ.

Шарҳ код такрор мекунад
JavaScript
// i-ро ба 1 меафзоем
i++;

// агар нарх аз 100 зиёд бошад
if (price > 100) { ... }

// return total * 0.9;
return total;
Шарҳ дониши нав медиҳад
JavaScript
// касса тангаҳои камтар аз
// 1 сомониро қабул намекунад, барои ҳамин боло мудаввар мекунем
const payment = Math.ceil(total);

// TODO(Мадина, то ҷумъа): иваз кардан
// ба дархост ба API, вақте ки он тайёр мешавад
  • Коди шарҳшударо хориҷ кунед. Он файлро ифлос мекунад, ва дар Git (дарси 19) тамоми таърих нигоҳ дошта шудааст — дар ҳар лаҳза баргардонидан мумкин аст.
  • Шарҳи кӯҳна аз надоштани он бадтар аст — он дурӯғ мегӯяд. Кодро тағйир медиҳед — шарҳи болои онро санҷед.
  • Мехоҳед шарҳ диҳед, ки порчаи код чӣ кор мекунад? Аввал кӯшиш кунед, ки онро ба функсия бо номи хуб бароред — ном ба «шарҳ»-е табдил мешавад, ки кӯҳна намешавад.
  • TODO — иҷозат аст, агар бо муаллиф ва мӯҳлат бошад. «Баъдтар ислоҳ мекунам»-и фаромӯшшуда солҳо кӯҳна мешавад.

Муфассалтар хонед: learn.javascript.ru — Шарҳҳо

Амал: мустаҳкам мекунем

Мантиқ ва баромадро ҷудо мекунем, фарқ кардани шарҳҳои муфидро аз садо меомӯзем.

ВАЗИФАИ 4.1

Садо ё шарҳи муфид

осон

Ҳашт шарҳ аз лоиҳаҳои воқеӣ. Ба массиви noise рақамҳои онҳоеро нависед, ки бефоидаанд (код такрор мекунанд, коди шарҳшуда, нақли номи функсия). Рақамҳо бо тартиби афзоиш.

Таҳрир кардан мумкин аст · Ctrl + Enter
/*
// 1
total = total + price; // нарх ба ҷамъбаст илова мекунем

// 2
const MAX_TRIES = 3; // пас аз 3 парол нодуруст вурудро мебандем — талаби хидмати амният

// 3
// return total * 0.9;

// 4
users.sort(byName); // корбаронро аз рӯи ном мураттаб мекунем

// 5
if (hour < 6) return "ночь"; // то соати 6-и пагоҳӣ масирҳо намераванд, барои ҳамин тарифи «шабона»

// 6
// TODO(Шаҳром, то ҷумъа): ба дархост ба API иваз кардан

// 7
let x = 5; // x ба панҷ баробар аст

// 8
// Функсия маҷмӯъро ҳисоб мекунад
function calcTotal(prices) { ... }
*/

const noise = [/* рақамҳо */];
console.log(noise.join(", "));
Натиҷаи интизоршаванда
1, 3, 4, 7, 8
Ишора 1

Кодро бо ангушт пӯшонед ва танҳо шарҳро бихонед: агар пас аз он чизеро фаҳмидед, ки худи код намегуфт, — шарҳ муфид аст.

Ишора 2

Муфидҳо — 2 (сабаби маҳдудият), 5 (сабаби тариф), 6 (TODO бо муаллиф ва мӯҳлат). Панҷи боқимонда — садо.

ВАЗИФАИ 4.2

Омори гурӯҳ

миёна

showStats якбора ҳам ҳисоб мекунад, ҳам чоп мекунад. Ҷудо кунед: calcStats(grades) объекти { average, best, passedCount }-ро бармегардонад (холи гузариш — собити PASS_SCORE = 56), formatStats(stats, total) массиви се сатр барои чопро бармегардонад (total — ҳамагӣ чанд баҳо), ва showStats танҳо онҳоро пайваст ва чоп мекунад. Баромад тағйир намеёбад.

Таҳрир кардан мумкин аст · Ctrl + Enter
function showStats(grades) {
  let sum = 0;
  let best = 0;
  let passed = 0;
  for (const grade of grades) {
    sum += grade;
    if (grade > best) best = grade;
    if (grade >= 56) passed++;
  }
  console.log("Средний балл: " + sum / grades.length);
  console.log("Лучший: " + best);
  console.log("Сдали: " + passed + " из " + grades.length);
}

showStats([90, 55, 72, 38, 85]);

console.log(JSON.stringify(calcStats([60, 40])));
console.log(typeof formatStats, typeof PASS_SCORE);
Натиҷаи интизоршаванда
Средний балл: 68
Лучший: 90
Сдали: 3 из 5
{"average":50,"best":60,"passedCount":1}
function number
Ишора 1

calcStats — тамоми давра, дар охир return { average: ..., best, passedCount: passed }. Дар дохил ягон console.log нест.

Ишора 2

showStats кӯтоҳ мешавад: const lines = formatStats(calcStats(grades), grades.length); ва давраи for (const line of lines) console.log(line);.

ВАЗИФАИ 4.3

Менюи чойхона: филтр ва нишонагузорӣ ҷудо

душвор

Ҳоло филтркунии таомҳо ва эҷоди <li> дар як давра омехта шудаанд. Ду функсия созед: getAffordableDishes(dishes, maxPrice) массиви таомҳоро бо нархи на аз maxPrice боло бармегардонад (ба DOM даст намезанад), renderMenu(list) рӯйхатро дар #menu тасвир мекунад. Баъд renderMenu(getAffordableDishes(dishes, 30))-ро даъват кунед. Сатрҳои санҷиши поёнро тағйир надиҳед.

Менюи чойхона · Ctrl + Enter
<h3>Меню до 30 сомони</h3>
<ul id="menu"></ul>
Пешнамоиш
Барои дидани натиҷа «Иҷро кардан»-ро пахш кунед.
Натиҷаи интизоршаванда
function function
3
2
Ишора 1

getAffordableDishes — ин dishes.filter(...) ё давра бо push аст; он массивро бармегардонад ва на дар бораи menu ва на дар бораи document медонад.

Ишора 2

Дар renderMenu(list) давраро аз рӯи list бо эҷоди li гузоред. Давраи кӯҳнаро бо ҳама чиз якбора хориҷ кунед — вагарна дар рӯйхат такрор мешавад ва санҷиш ба ҷои 3 шашто нишон медиҳад.

05 Рефакторинг: шаклро тағйир медиҳем, на рафторро

Рефакторинг — ин беҳтар кардани сохти код бе тағйири он чизе, ки кор мекунад. Барои корбар чизе тағйир наёфт: ҳамон тугмаҳо, ҳамон рақамҳо. Барои шумо ҳама чиз тағйир ёфт: код фаҳмотар шуд ва минбаъд инкишоф додани он осонтар аст. Калимаи асосӣ дар ин ҷо — «бе тағйир»: агар дар роҳ рафторро бешуурона тағйир додед, ин аллакай рефакторинг нест, балки хатои нав аст.

Монандӣ аз ҳаёт

Тозакунии ошхонаи чойхона ҳангоми кор: корддонҳо дар як қуттӣ, зираворҳо аз рӯи алифбо, тахтаҳои тоза. Меҳмонон палавро мегиранд, аммо ошпазҳо тезтар мепазанд ва камтар хато мекунанд. Тозакуниро оғоз кардан ва дар баробар дорупази палавро иваз кардан мумкин нест — вагарна маълум нест, кадом чиз маззаро бад кард.

Давраи кории бехатар

  1. Рафторро собит кунед. Пеш аз тағйир додани чизе, кодро иҷро кунед ва сабт кунед, ки барои якчанд вуруд чӣ чоп мекунад — аз ҷумла сарҳадӣ (0, холӣ, дақиқан остона). Инҳо «тестҳои» шумо ҳастанд.
  2. Як қадами хурд: иваз кардем → иҷро кардем → баромад ҳамон. Собитро баровардем → иҷро кардем → ҳамон. Даҳ ислоҳи пай дар пай накунед.
  3. Тартиби қадамҳо аз оддӣ ба мураккаб: номҳо → собитҳо → хориҷ кардани партов ва коди мурда → бозгашти барвақтӣ → ҷудо кардани функсияҳо → бартараф кардани такрорҳо → ҷудо кардани мантиқ ва баромад.
  4. Вайрон шуд — бозгашт кунед ба ҳолати охирини корӣ. Дар Git ин як фармон аст; барои ҳамин пас аз ҳар қадами муваффақ commit мекунем (дарси 19), масалан rename vars in cart.js.
  5. Ду кулоҳ. Ё шумо рефакторинг мекунед, ё хатоиро ислоҳ мекунед/функсия илова мекунед. Якбора — мумкин нест. Дар роҳ хаторо ёфтед — сабт кунед ва ба он бо commit-и алоҳида баргардед.

Мини-тестҳо дар як функсия

Барои санҷиши рефакторинг абзорҳои махсус лозим нестанд. Функсияи хурде кофист, ки ҷавобро бо интизоршаванда муқоиса мекунад:

check — тести худсохт · Ctrl + Enter
function check(name, actual, expected) {
  console.log(`${actual === expected ? "OK  " : "FAIL"} ${name}`);
}

const isAdult = age => age >= 18;

check("18 — взрослый", isAdult(18), true);
check("17 — не взрослый", isAdult(17), false);
check("0 — не взрослый", isAdult(0), false);

Чек-листи ягонаи сифати код

То ки «тоза» маънои «чунон ки ба ман маъқул аст»-ро надошта бошад, мо чек-листи умумии 12 банд дорем — версияи пурраи чопӣ дар охири дарс. Бандҳои 1–8 дар бораи код, 9–12 дар бораи лоиҳа. Ҳоло ҳашти аввал лозиманд:

№Банди чек-лист
1Номҳо мегӯянд, ки ин чист (a, data, temp нест; булӣ — is/has/can)
2Андоза: функсия як чизро мекунад ва дар экран ҷо мешавад
3DRY: копипаст нест — такроршаванда баровардашуда
4Бозгашти барвақтӣ: дарунҷойгирӣ аз 2–3 сатҳ чуқуртар нест, else-и зиёдатӣ нест
5Собитҳо: рақамҳо ва сатрҳои ҷодуӣ нестанд
6Мантиқ ≠ намоиш: ҳисобҳо ба DOM ва консол даст намезананд
7Шарҳҳо «барои чӣ»-ро шарҳ медиҳанд; коди шарҳшуда нест
8Тоза: console.log-ҳои ислоҳӣ, коди истифоданашаванда, var нест

Муфассалтар хонед: refactoring.guru — Рефакторинг чист

Амал: баҳо медиҳем ва рефакторинг мекунем

Аввал ёд мегирем, ки мушкилотро бинем — кодро аз рӯи чек-лист баҳо медиҳем. Баъд ислоҳ мекунем.

ВАЗИФАИ 5.1

Кодро аз рӯи чек-лист баҳо диҳед

осон

Функсияро бихонед (он дар шарҳ аст, иҷро кардани он лозим нест) ва ба массиви violations рақамҳои бандҳои вайроншудаи чек-листро нависед (1–8, бо тартиби афзоиш).

Таҳрир кардан мумкин аст · Ctrl + Enter
/*
function calc(l) {
  let t = 0;
  console.log("calc даъват шуд");
  for (let i = 0; i < l.length; i++) {
    t = t + l[i].p * l[i].q;
  }
  if (t > 500) {
    t = t - t * 0.05;
  }
  return t;
}
*/

const violations = [/* рақамҳои бандҳо */];
console.log(violations.join(", "));
Натиҷаи интизоршаванда
1, 5, 8
Ишора 1

Номҳои calc, l, t, p, q — банди 1. Рақамҳои 500 ва 0.05 бе ном — банди 5. Ва сатри бо console.log дар дохили ҳисоб чӣ мекунад?

Ишора 2

Функсия кӯтоҳ, такрор нест, дарунҷойгирӣ як аст, шарҳ нест — бандҳои 2, 3, 4, 6, 7 дар ин ҷо вайрон нашудаанд.

ВАЗИФАИ 5.2

Бо корти профил чӣ нодуруст аст

миёна

Боз як функсия. Вайронкуниҳоро ёбед (бандҳои 1–8). Бодиққат: як вайронкунӣ метавонад дар рақами аз назар оддӣ пинҳон бошад.

Таҳрир кардан мумкин аст · Ctrl + Enter
/*
function showProfile(user) {
  const box = document.createElement("div");   // div эҷод мекунем
  if (user) {
    if (user.name) {
      if (user.birthYear) {
        const age = 2026 - user.birthYear;
        box.textContent = user.name + ", синну сол: " + age;
        document.body.append(box);
      }
    }
  }
}
*/

const violations = [/* рақамҳои бандҳо */];
console.log(violations.join(", "));
Натиҷаи интизоршаванда
4, 5, 6, 7
Ишора 1

Дарунҷойгирии се if — банди 4. Шарҳи «div эҷод мекунем» код такрор мекунад — банди 7.

Ишора 2

Рақами 2026 — соле, ки ба код дӯхта шудааст: пас аз як сол синну сол нодуруст ҳисоб мешавад (банди 5). Ва боз: функсия синну солро ҳисоб мекунад ва дар саҳифа тасвир мекунад — кадом банд дар ин бора аст?

ВАЗИФАИ 5.3

Сабади мағоза: рефакторинги пурра

душвор

Функсияи f маблағи фармоишро ҳисоб мекунад: маҳсулот → промокод (NAVRUZ −15%, STUDENT −10%) → интиқол 25 сомонӣ, агар маблағ аз 300 камтар бошад → мудаввар кардан. Онро аз рӯи чек-лист ба тартиб оваред ва натиҷаҳоро нигоҳ доред:

  • функсия calcOrderTotal(items, promoCode) ном дорад, дар маҳсулот майдонҳои price ва quantity (дар тестҳо онҳо аллакай ҳамин тавр номгузорӣ шудаанд);
  • собитҳои FREE_DELIVERY_FROM, DELIVERY_PRICE ва объекти PROMO_DISCOUNTS (рамз → фоиз);
  • бе else; ҳисоби зерҷамъ — функсияи алоҳидаи calcSubtotal(items).
Таҳрир кардан мумкин аст · Ctrl + Enter
function f(a, c) {
  let r = 0;
  for (let i = 0; i < a.length; i++) {
    r += a[i].p * a[i].q;
  }
  if (c === "NAVRUZ") {
    r = r - r * 15 / 100;
  } else {
    if (c === "STUDENT") {
      r = r - r * 10 / 100;
    }
  }
  if (r < 300) {
    r = r + 25;
  }
  return Math.round(r);
}

const small = [{ price: 50, quantity: 2 }, { price: 120, quantity: 1 }];
const big = [{ price: 200, quantity: 3 }];

console.log(calcOrderTotal(small, ""));
console.log(calcOrderTotal(small, "NAVRUZ"));
console.log(calcOrderTotal(small, "STUDENT"));
console.log(calcOrderTotal(big, ""));
console.log(calcOrderTotal(big, "NAVRUZ"));
console.log(calcOrderTotal(big, "UNKNOWN"));
console.log(calcSubtotal(small));
console.log(typeof FREE_DELIVERY_FROM, typeof DELIVERY_PRICE, typeof PROMO_DISCOUNTS);
console.log(calcOrderTotal.toString().includes("else"));
Натиҷаи интизоршаванда
245
212
223
600
510
600
220
number number object
false
Ишора 1

Нақша қадам ба қадам: 1) иваз кунед, 2) собитҳоро бароред, 3) calcSubtotal тавассути давраи for...of ё reduce, 4) промокод: const percent = PROMO_DISCOUNTS[promoCode] || 0; — ба ҷои ду if-и дарунҷойгир. Пас аз ҳар қадам иҷро кунед ва муқоиса намоед.

Ишора 2

Тахфиф: const discounted = subtotal - subtotal * percent / 100;. Интиқол: return Math.round(discounted)-и барвақтӣ барои маблағ аз остона, вагарна Math.round(discounted + DELIVERY_PRICE). Остона бо маблағи пас аз тахфиф муқоиса мешавад — мисли коди аслӣ.

ВАЗИФАИ 5.4

Рефакторинге, ки кодро вайрон кард

миёна

Ҳамкор функсияи баҳодиҳиро «рефакторинг кард»: зебо, аммо рафтор тағйир ёфт. Тестҳо (check) дар ҷое, ки чизе вайрон аст, FAIL чоп мекунанд. Сабабро ёбед ва тавре ислоҳ кунед, ки ҳамаи тестҳо OK шаванд. Тестҳоро тағйир надиҳед: баҳоҳои дуруст — 86 ва боло → 5, аз 71 → 4, аз 56 → 3, поёнтар → 2.

Таҳрир кардан мумкин аст · Ctrl + Enter
const PASS_SCORE = 56;

function getGrade(score) {
  if (score > 86) return 5;
  if (score >= 71) return 4;
  if (score > PASS_SCORE) return 3;
  return 2;
}

function check(name, actual, expected) {
  console.log(`${actual === expected ? "OK  " : "FAIL"} ${name}`);
}

check("90 → 5", getGrade(90), 5);
check("86 → 5", getGrade(86), 5);
check("71 → 4", getGrade(71), 4);
check("56 → 3", getGrade(56), 3);
check("55 → 2", getGrade(55), 2);
check("0 → 2", getGrade(0), 2);
Натиҷаи интизоршаванда
OK 90 → 5
OK 86 → 5
OK 71 → 4
OK 56 → 3
OK 55 → 2
OK 0 → 2
Ишора 1

FAIL дақиқан дар сарҳадҳо рух медиҳад. Ба аломатҳои муқоиса нигоҳ кунед: дар куҷо ба ҷои >= аломати > меистад?

Ишора 2

Хатоҳо дутоанд: дар сатри якум бо 86 ва дар сатр бо PASS_SCORE. Дарс: қиматҳои сарҳадӣ ҳатман ба тестҳо дохил мешаванд.

ВАЗИФАИ 5.5

Ҳозиршавӣ: давраҳо → методҳои массив

душвор

Функсияи report «аълохонон»-ро ҳисоб мекунад (8+ машғулотро ҳозир шудаанд; номҳо — бо ҳарфи калон) ва ҳозиршавии миёнаро. Ба getExcellentNames(students) (тавассути filter ва map) ва calcAverageVisits(students) (тавассути reduce) тақсим кунед, остонаро ба MIN_VISITS_FOR_EXCELLENT бароред. Дар натиҷа дар ягон аз се функсия давраи for ( набояд бошад. Баромад ҳамон.

Таҳрир кардан мумкин аст · Ctrl + Enter
function report(students) {
  const names = [];
  for (let i = 0; i < students.length; i++) {
    if (students[i].visited >= 8) {
      names.push(students[i].name.toUpperCase());
    }
  }
  let total = 0;
  for (let i = 0; i < students.length; i++) {
    total = total + students[i].visited;
  }
  const avg = total / students.length;
  return names.join(", ") + " | среднее: " + avg;
}

const group = [
  { name: "Рустам", visited: 10 },
  { name: "Зарина", visited: 7 },
  { name: "Нилуфар", visited: 8 },
  { name: "Далер", visited: 4 },
];

console.log(report(group));
console.log(report([{ name: "Фарход", visited: 9 }]));
console.log(report([{ name: "Анора", visited: 3 }]));
console.log(typeof MIN_VISITS_FOR_EXCELLENT);
console.log([report, getExcellentNames, calcAverageVisits].some(fn => fn.toString().includes("for (")));
Натиҷаи интизоршаванда
РУСТАМ, НИЛУФАР | среднее: 7.25
ФАРХОД | среднее: 9
| среднее: 3
number
false
Ишора 1

getExcellentNames: аввал students.filter(s => s.visited >= MIN_VISITS_FOR_EXCELLENT), баъд ба натиҷа .map(s => s.name.toUpperCase()).

Ишора 2

calcAverageVisits: students.reduce((sum, s) => sum + s.visited, 0) / students.length. Он гоҳ report — як сатр аст, ки натиҷаҳои ду функсияро мечаспонад.

06 Ҷамъбасти лоиҳа: npm run build

Дар дарси 17 шумо лоиҳаро дар Vite эҷод кардед ва npm run dev-ро иҷро кардед. Ин реҷаи таҳия аст: Vite файлҳоро «чунон ки ҳастанд» медиҳад, саҳифаро фавран навсозӣ мекунад ва ишораҳо барои таҳиягарро илова менамояд. Барои сайти ҳақиқӣ чунин реҷа мувофиқ нест — код фишурда нашудааст, зиёдатӣ аст, ва сервер танҳо дар ноутбуки шумо кор мекунад. Барои нашр ҷамъбаст (build) лозим аст.

Монандӣ аз ҳаёт

Реҷаи таҳия — ошхона ҳангоми пухтан аст: дегҳо, корддонҳо, пӯстҳо дар сари миз. Ҷамъбаст — хӯроки тайёр, ки зебо дар контейнер барои бо худ бурдан печонда шудааст. Ба муштарӣ контейнер лозим аст, на тамоми ошхона. Папкаи dist — ҳамон «контейнер»-и печондашудаи сайти шумост.

Ҷамъбаст чӣ кор мекунад

  1. Ҷамъ мекунад ҳамаи модулҳои шуморо (import/export) ба якчанд файл.
  2. Минификатсия мекунад: фосилаҳо, шарҳҳоро хориҷ мекунад, номҳои тағйирёбандаҳоро кӯтоҳ мекунад. Файл якчанд маротиба хурдтар мешавад — саҳифа тезтар бор мешавад.
  3. Истифоданашударо мепартояд (tree shaking): агар китобхонаро пайваст карда бошед, аммо як функсияро истифода баред, зиёдатӣ ба сайт намеафтад.
  4. Ба номи файлҳо хеш илова мекунад (index-Ab12Cd34.js): код тағйир ёфт — ном иваз шуд, ва браузер версияи тозаро зеркашӣ мекунад, на кӯҳнаро аз кэш мегирад.
  5. Натиҷаро ба папкаи dist/ мегузорад — маҳз онро ба хостинг медиҳанд.
Терминал — ҷамъ мекунем ва натиҷаро мебинем
npm install        # если ещё не ставили зависимости
npm run build      # запускает «vite build», результат — в папке dist/
npm run preview    # локальный сервер для готовой сборки: http://localhost:4173

Пас аз ҷамъбасти лоиҳаи хурд дар dist/ чӣ меистад:

Сохтори dist/
dist/
├── index.html                  ← точка входа, ссылки на файлы из assets/
├── favicon.svg                 ← всё из папки public/ копируется как есть
└── assets/
    ├── index-Ab12Cd34.js       ← весь ваш JavaScript, сжатый
    └── index-Ef56Gh78.css      ← весь CSS, сжатый
Се хатои маъмул

1. «Дар dev кор мекунад, аммо дар build — не». Ҷамъбаст сахттар аст: он import-ҳои вайрон ва хатоҳои имлоиро дар роҳҳо намебахшад. Ҳамеша npm run build-ро пеш аз деплой иҷро кунед.
2. Ҳарфи калон ва хурд дар номи файлҳо. Дар Windows ва macOS import "./Header.js" файли header.js-ро меёбад. Аммо хостингҳо дар Linux кор мекунанд, ки дар он Header.js ва header.js — файлҳои гуногунанд: дар компютери шумо ҳама чиз хуб аст, аммо дар Vercel ҷамъбаст меафтад. Номи файлҳо ва import-ҳоро айнан як хел нависед.
3. dist/index.html-ро бо дукарата зер кардан кушодан. Роҳҳо дар он бо /assets/… оғоз мешаванд ва аз низоми файлӣ ёфт намешаванд — саҳифа холӣ мешавад. Барои санҷиш npm run preview ҳаст.

Windows ва macOS

Фармонҳои npm дар ҳама ҷо яксонанд. Дар Windows онҳоро дар PowerShell, «Терминал»-и VS Code ё Git Bash иҷро кунед; дар macOS — дар «Терминал» ё дар терминали дарунсохти VS Code (Ctrl + `). Санҷед, ки Node насб шудааст: node -v. Агар npm run build менависад «vite: command not found» — шумо дар папкаи лоиҳа нестед ё npm install-ро иҷро накардаед.

Папкаи dist-ро ба Git commit намекунем

Ин файли «ҳосилшуда» аст: онро ҳамеша бо фармони build гирифтан мумкин аст. Дар .gitignore (дарси 19) сатрҳои node_modules ва dist бояд бошанд — дар қолаби Vite онҳо аллакай ҳастанд. Хостинг худаш ҷамъбастро аз рӯи коди шумо иҷро мекунад.

Муфассалтар хонед: vite.dev — Ҷамъбаст барои продакшн

Амал: мустаҳкам мекунем

ВАЗИФАИ 6.1

Чӣ дар бораи ҷамъбаст дуруст аст

осон

Шаш изҳорот. Ба массиви correct ҳарфҳои дурустҳоро нависед (бо тартиби алифбо, дар нохунакҳо).

Таҳрир кардан мумкин аст · Ctrl + Enter
// A. Папкаи dist-ро бояд ба репозиторий commit кард.
// B. Дар dist файлҳои минификатсияшудаи JS ва CSS меистанд.
// C. npm run preview версияи маҳаллӣ ҷамъшудаи сайтро нишон медиҳад.
// D. Хеш дар номи файл (index-Ab12Cd34.js) лозим аст, то браузер пас аз навсозӣ версияи тозаро гирад.
// E. Агар дар реҷаи dev ҳама чиз кор кунад, ҷамъбаст ҳатман мегузарад.
// F. dist/index.html бо дукарата зеркунӣ аз папка боэътимод кушода мешавад.

const correct = [/* "A", "B" ... */];
console.log(correct.join(", "));
Натиҷаи интизоршаванда
B, C, D
Ишора 1

Се изҳорот нодурустанд: dist — натиҷаи ҷамъбаст аст, на сарчашма; дар dev ва build код ба таври гуногун санҷида мешавад; роҳҳо дар index.html мутлақанд.

Ишора 2

Нодурустҳо: A, E, F. Дурустҳо — се боқимонда.

ВАЗИФАИ 6.2

Шикорчии ҳарфи калон/хурд

миёна

findCaseMismatches(files, imports)-ро нависед — он он import-ҳоеро бармегардонад, ки дар Windows/macOS кор мекунанд, аммо дар хостинги Linux ҷамъбастро вайрон мекунанд: файл бо чунин роҳ ҳаст, аммо танҳо агар ҳарфи калон ва хурдро фарқ накунем. Import-и файли вуҷуднадошта дар ҳар регистр ба ҷавоб намеафтад. Тартиб — мисли дар imports.

Таҳрир кардан мумкин аст · Ctrl + Enter
const files = ["src/Header.js", "src/footer.js", "src/utils/format.js", "public/Logo.png"];
const imports = ["src/header.js", "src/footer.js", "src/utils/Format.js", "public/Logo.png", "src/missing.js"];

function findCaseMismatches(files, imports) {
  // коди шумо
}

console.log(JSON.stringify(findCaseMismatches(files, imports)));
Натиҷаи интизоршаванда
["src/header.js","src/utils/Format.js"]
Ишора 1

Import «вайрон» аст, агар !files.includes(path) бошад, аммо файле ёфт шавад, ки file.toLowerCase() === path.toLowerCase() дорад.

Ишора 2

return imports.filter(path => ...), ки дар он шарт — !files.includes(path) ва files.some(...) бо муқоиса дар регистри паст аст.

07 Тағйирёбандаҳои муҳит ва сирҳо

Нишонии API дар компютери шумо яктост, дар версияи «ҷангии» сайт — дигар. Андозаи саҳифа, номи барнома, калид ба хидмати обуҳаво — ҳамаи инҳо танзимот ҳастанд, ки онҳоро ба код дӯхтан лозим нест. Онҳоро ба тағйирёбандаҳои муҳит мебароранд — файли алоҳида, ки ҳангоми оғоз ва ҷамъбаст хонда мешавад.

Монандӣ аз ҳаёт

Дорупази палав як аст, аммо шумораи порсияҳо аз ҳолат вобаста аст: барои оила — як килограмм биринҷ, барои тӯй — даҳто. Шумо дорупазро аз нав намеменависед, балки «танзим»-ро дар коғазчаи дар ошхона иваз мекунед. Тағйирёбандаҳои муҳит — чунин коғазчаанд: код як аст, ва қиматҳо барои ҳар муҳит (ноутбуки шумо, сайт дар интернет) худӣ.

Дар Vite чӣ тавр кор мекунад

Дар решаи лоиҳа (дар паҳлӯи package.json) файли .env-ро эҷод кунед:

.env
VITE_API_URL=https://dummyjson.com
VITE_PAGE_SIZE=12
VITE_APP_NAME=Лавка MakeFirstStep
DB_PASSWORD=не-попадёт-в-браузер

Дар код тавассути import.meta.env мехонем:

src/config.js
export const API_URL = import.meta.env.VITE_API_URL;
export const PAGE_SIZE = Number(import.meta.env.VITE_PAGE_SIZE);   // ҳамаи қиматҳо — сатрҳоянд!

console.log(import.meta.env.DB_PASSWORD);   // undefined: бе префикси VITE_ тағйирёбанда пинҳон аст
console.log(import.meta.env.MODE);          // "development" дар dev, "production" дар build
console.log(import.meta.env.DEV);           // true танҳо дар реҷаи таҳия
  • Префикси VITE_ — ягона тағйирёбандаҳое, ки Vite ба коди браузерӣ медиҳад. Боқӣ ноаён мемонанд.
  • Қиматҳо — ҳамеша сатрҳо. VITE_PAGE_SIZE=12 "12"-ро медиҳад, VITE_DEBUG=false бошад — сатри "false"-ро, ки дар шарт ростӣ ҳисоб мешавад! Худатон табдил диҳед: Number(...), value === "true".
  • Пас аз таҳрири .env аз нав оғоз кунед npm run dev-ро — тағйирёбандаҳо ҳангоми оғоз хонда мешаванд.
  • Дарунсохтҳо: import.meta.env.MODE, DEV, PROD, BASE_URL.

Кадом файлҳои .env мешаванд

ФайлКай бор мешавадДар Git?
.envҳамешамешавад, агар дар он сирр набошад
.env.localҳамеша, қиматҳои шахсии шумоне (*.local дар .gitignore)
.env.developmentтанҳо npm run devмешавад
.env.productionтанҳо npm run buildмешавад
.env.production.localтанҳо build, қиматҳои шахсӣне

Файли «реҷаи худӣ» .env-и умумиро мепӯшонад. Тағйирёбандаҳое, ки аллакай дар система ё дар хостинг муайян шудаанд, ҳамаро мепӯшонанд.

Қоидаи асосӣ: дар браузер сирр нест

Қиматҳои VITE_* ҳангоми ҷамъбаст бевосита ба файли JavaScript ҷойгузин мешаванд — ҳар корбар DevTools → Sources-ро кушода, онҳоро мехонад. Барои ҳамин VITE_ — барои танзимоти оммавӣ (нишонии API, ном, андозаи саҳифа) аст. Калидҳои пардохт, паролҳои пойгоҳи додаҳо, токенҳо бо ҳуқуқи навиштан ба чунин тағйирёбандаҳо гузоштан мумкин нест: барои онҳо сервери худӣ ё функсияҳои серверӣ лозим аст — ин мавзӯи курси оянда аст.

Терминал — худамон боварӣ ҳосил мекунем: қимат дар ҷамъбаст меистад
# macOS / Linux
grep -r "dummyjson" dist/assets

# Windows (PowerShell)
Select-String -Path dist\assets\*.js -Pattern "dummyjson"

Чӣ кор кардан, то ошкор нашавад

  1. Файлҳои шахсӣ дар .gitignore: сатрҳои .env.local ва *.local. Бо фармони git status санҷед — файл дар рӯйхат набояд бошад.
  2. Файли .env.example-ро эҷод кунед — нусхаи .env бо қиматҳои холӣ. Он ба Git меравад ва ба ҳамкор мегӯяд, ки кадом тағйирёбандаҳо лозиманд: VITE_API_URL=
  3. Дар README нависед: «.env.example-ро ба .env нусха кунед ва пур намоед».
  4. Дар хостинг қиматҳоро дар панел ворид мекунанд (Vercel — Settings → Environment Variables, GitHub — Settings → Secrets and variables), на дар репозиторий.
  5. Агар калид тасодуфан ба commit афтод — онро дуздидашуда ҳисоб кунед: фавран бекор кунед ва дар хидмат нав бароред. Хориҷ кардани commit кофӣ нест: таърихи Git ва ботҳои GitHub-ро скан мекунанд, онро аллакай гирифта тавонистаанд.
.gitignore
node_modules
dist
.env.local
*.local
Windows ва macOS

Нусха кардани файл: macOS — cp .env.example .env, Windows PowerShell — copy .env.example .env. Номи файл бо нуқта оғоз мешавад — дар Проводники Windows ва Finder дар macOS чунин файлҳо метавонанд пинҳон бошанд (Finder: Cmd + Shift + .); дар VS Code онҳо ҳамеша намоёнанд.

Муфассалтар хонед: vite.dev — Тағйирёбандаҳои муҳит ва реҷаҳо

Амал: мустаҳкам мекунем

import.meta.env танҳо дар дохили лоиҳаи Vite кор мекунад, барои ҳамин дар ин ҷо мантиқ-ро бо объектҳо ва сатрҳои оддӣ машқ мекунем.

ВАЗИФАИ 7.1

Браузер чиро мебинад

осон

getPublicEnv(env)-ро нависед: он объекти навро танҳо бо он тағйирёбандаҳое бармегардонад, ки Vite ба браузер медод (номҳо бо VITE_ оғоз мешаванд).

Таҳрир кардан мумкин аст · Ctrl + Enter
const env = {
  VITE_API_URL: "https://api.example.com",
  VITE_APP_NAME: "Мой магазин",
  DB_PASSWORD: "x1",
  SECRET_KEY: "y2",
  MODE: "production",
};

function getPublicEnv(env) {
  // коди шумо
}

console.log(JSON.stringify(getPublicEnv(env)));
Натиҷаи интизоршаванда
{"VITE_API_URL":"https://api.example.com","VITE_APP_NAME":"Мой магазин"}
Ишора 1

Object.entries(env) объектро ба массиви ҷуфтҳои [калид, қимат] табдил медиҳад. Ҷуфтҳоеро монед, ки калидашон key.startsWith("VITE_") аст.

Ишора 2

Object.fromEntries( объектро аз ҷуфтҳо бозпас ҷамъ мекунад: дар дохил Object.entries(env).filter(...), return пеш аз тамоми ифода.

ВАЗИФАИ 7.2

.env-ро бо даст мехонем

миёна

parseEnv(text)-ро нависед: матни файли .env-ро ба объект таҳлил мекунад. Қоидаҳо: сатрҳои холӣ ва сатрҳои бо # оғозшаванда гузашта мешаванд; формат КАЛИД=қимат; фосилаҳо дар гирди калид ва қимат хориҷ мешаванд; қимат дар нохунак — бе нохунак; аломати = дар дохили қимат иҷозат аст (танҳо аз рӯи аввалӣ тақсим мекунем). Ҳамаи қиматҳо сатр мемонанд.

Таҳрир кардан мумкин аст · Ctrl + Enter
const text = `
# адрес API
VITE_API_URL=https://dummyjson.com

VITE_APP_NAME="Лавка MakeFirstStep"
VITE_PAGE_SIZE = 12
VITE_FILTER=sort=asc
`;

function parseEnv(text) {
  // коди шумо
}

console.log(JSON.stringify(parseEnv(text)));
Натиҷаи интизоршаванда
{"VITE_API_URL":"https://dummyjson.com","VITE_APP_NAME":"Лавка MakeFirstStep","VITE_PAGE_SIZE":"12","VITE_FILTER":"sort=asc"}
Ишора 1

Аз рӯи text.split("\n") гузаред. Барои ҳар сатр: line.trim(); агар холӣ ё бо # оғоз шавад — continue.

Ишора 2

Мавқеи баробарии аввал: const index = line.indexOf("="). Калид — line.slice(0, index).trim(), қимат — line.slice(index + 1).trim(). Нохунакҳо: агар қимат бо " оғоз ва анҷом ёбад, аз ҳар тараф як аломатро бурред: value.slice(1, -1).

ВАЗИФАИ 7.3

Домҳои сатри "false"

миёна

Аввал пешгӯӣ кунед, ки сатри якум Boolean("false") чӣ чоп мекунад. Баъд readFlag(value)-ро нависед — true танҳо барои сатри "true", вагарна false — ва readNumber(value, fallback) — рақам аз сатр, ва агар қимат нест (undefined), холӣ ё рақам нест, пас fallback.

Таҳрир кардан мумкин аст · Ctrl + Enter
console.log(Boolean("false"));

function readFlag(value) {
  // коди шумо
}

function readNumber(value, fallback) {
  // коди шумо
}

console.log(readFlag("true"), readFlag("false"), readFlag(undefined));
console.log(readNumber("12", 6), readNumber(undefined, 6), readNumber("abc", 6), readNumber("", 6));
Натиҷаи интизоршаванда
true
true false false
12 6 6 6
Ишора 1

Ҳар сатри ғайрихолӣ — ростӣ аст, ҳатто "false". Барои ҳамин парчамро бо сатр муқоиса мекунем: value === "true".

Ишора 2

Барои рақам: агар value === undefined || value === "" бошад — fallback-ро баргардонед. Вагарна const number = Number(value); ва Number.isNaN(number) ? fallback : number.

ВАЗИФАИ 7.4

Шикорчии сирҳо

душвор

Пеш аз commit скан кардани код фоиданок аст. findSecrets(lines)-ро нависед: рақамҳои сатрҳо-ро (аз 1 ҳисоб карда) бармегардонад, ки дар онҳо ба номи дорои key, token, secret ё password (дар ҳар регистр) литерали сатрӣ бо дарозии аз 8 аломат таъин мешавад (тавассути = ё :). Хондан аз import.meta.env, сатрҳои холӣ ва кӯтоҳ сир ҳисоб намешаванд.

Таҳрир кардан мумкин аст · Ctrl + Enter
const lines = [
  'const API_URL = import.meta.env.VITE_API_URL;',
  'const apiKey = "sk_live_51Hh83jKd92hs";',
  'fetch(`${API_URL}/products`);',
  "const password = 'qwerty12345';",
  'const token = import.meta.env.VITE_TOKEN;',
  'const secret = "";',
  'const authToken = "Bearer eyJhbGciOiJI";',
  'const title = "My secret garden";',
];

function findSecrets(lines) {
  // коди шумо
}

console.log(findSecrets(lines).join(", "));
Натиҷаи интизоршаванда
2, 4, 7
Ишора 1

Дар ин ҷо ифодаи регулярӣ кумак мекунад. Скелет: /(key|token|secret|password)\w*\s*[:=]\s*["'`][^"'`]{8,}["'`]/i — аз рӯи қисмҳо таҳлил кунед, ки ҳар яки онҳо чӣ маъно дорад.

Ишора 2

Аз рӯи сатрҳо бо индекс гузаред ва ба массив index + 1-ро барои онҳое ҷамъ кунед, ки pattern.test(line) дурӯғ нест. Сатри 8 мувофиқ нест: калимаи secret дар дохили матн меистад, на дар номи тағйирёбанда.

08 Деплой: Vercel ва GitHub Pages

Деплой — нашри сайт дар интернет, то ҳар кас онро аз рӯи истинод кушояд. То лоиҳа дар ноутбуки шумост, ин машқ аст. Вақте ки он истинод дорад — ин портфолио аст. Мо ду усули ройгонро барои сайтҳои статикӣ таҳлил мекунем (ва лоиҳаҳои шумо дар Vite — маҳз чунинанд).

Монандӣ аз ҳаёт

Шумо самбӯсаро дар хона пухтед — лазиз аст, аммо танҳо наздикон мечашанд. Деплой — кушодани сандуқ дар бозор: ҳамон маҳсулот, аммо акнун он нишонӣ дорад, ва ҳама ба назди он омада метавонанд. Хостинг — ҷой дар бозор аст, ва истинод — рақами сандуқи шумо.

Пеш аз деплой: чек-листи кӯтоҳ

  • npm run build бе хато мегузарад, npm run preview сайти корӣ нишон медиҳад.
  • Лоиҳа дар репозиторий дар GitHub меистад (дарси 19), шохаи бо коди корӣ фиристода шудааст: git push.
  • Дар репозиторий .env.local ва сирҳо нестанд; .env.example ҳаст.
  • Ҳарфи калон ва хурди номҳои файлҳо ва import-ҳо мувофиқат мекунад.

Усули 1. Vercel

Vercel худаш Vite-ро меёбад, худаш лоиҳаро ҷамъ мекунад ва пас аз ҳар git push сайтро навсозӣ мекунад. Барои навомӯз — кӯтоҳтарин роҳ.

  1. vercel.com-ро кушоед ва бо тугмаи Continue with GitHub ворид шавед (тарифи Hobby барои лоиҳаҳои шахсӣ ройгон аст).
  2. Add New… → Project-ро пахш кунед. Vercel репозиторийҳои шуморо нишон медиҳад: даркориро ёбед ва Import-ро пахш кунед (бори аввал дастрасӣ ба репозиторийҳоро иҷозат диҳед).
  3. Дар экрани танзим санҷед: Framework Preset — Vite (худаш муайян мешавад), Build Command — npm run build, Output Directory — dist.
  4. Environment Variables-ро кушоед ва тағйирёбандаҳоро аз .env-и худ илова кунед (масалан, VITE_API_URL) — яктоӣ: ном ва қимат. Файли .env-ро Vercel аз репозиторий намехонад.
  5. Deploy-ро пахш кунед. Пас аз як дақиқа нишонии намуди номи-лоиҳа.vercel.app пайдо мешавад. Ин истиноди зиндаи шумост.
  6. Минбаъд: ҳар git push ба шохаи асосӣ сайтро навсозӣ мекунад, ва ҳар шохаи дигар нишонии алоҳидаи пешнамоиш мегирад — қулай аст барои нишон додани таҳрирҳо пеш аз ҷамъкунӣ.
Терминал — обновление сайта = обычный push
git add .
git commit -m "fix price format"
git push
# Vercel сам запустит npm run build и обновит сайт
Агар сайт кушода шуд, аммо маълумот бор намешавад

DevTools → Network-ро кушоед (дарси 19). Дархост ба undefined/products меравад? Яъне тағйирёбанда дар Vercel илова нашудааст ё префикси VITE_ надорад. Тағйирёбандаро пас аз деплой илова кардед — ин кофӣ нест: тағйирёбандаҳо ҳангоми ҷамъбаст ҷойгузин мешаванд, барои ҳамин Deployments → … → Redeploy-ро кушоед.

Усули 2. GitHub Pages

Хостинги ройгон бевосита дар репозиторий (барои репозиторийҳои оммавӣ). Нишонӣ — https://логини-шумо.github.io/номи-репозиторий/. Ба қисми охирин диққат диҳед: сайт на дар реша, балки дар зерпапка зиндагӣ мекунад. Барои ҳамин ба Vite бояд гуфт, ки файлҳоро аз куҷо гирад — танзими base.

vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  base: "/my-shop/",   // ← номи дақиқи репозиторий байни хатҳои моил
});

Бе base саҳифа холӣ бор мешавад: дар консол 404 ба /assets/index-….js мешавад, зеро браузер файлро дар решаи github.io меҷӯяд, на дар репозиторийи шумо. Дар код истиноди файлҳоро аз public/ тавассути import.meta.env.BASE_URL месозем, на "/logo.png"-ро бо даст менависем.

  1. base-ро дар vite.config.js муайян кунед, npm run build ва npm run preview-ро иҷро кунед (нишонии пешнамоиш /my-shop/-ро дар бар мегирад).
  2. Кодро ба GitHub фиристед: git push.
  3. Дар репозиторий: Settings → Pages → дар майдони Source GitHub Actions-ро интихоб кунед.
  4. Файли .github/workflows/deploy.yml-ро эҷод кунед (дар зер), commit кунед ва фиристед.
  5. Ҷадвали Actions: тики сабзро интизор шавед. Нишонии сайт дар Settings → Pages пайдо мешавад.
  6. Тағйирёбандаҳо лозиманд? Settings → Secrets and variables → Actions → Variables, ва дар workflow онҳоро ба қадами ҷамъбаст диҳед (ниг. env дар зер).
.github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: true

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: lts/*
          cache: npm
      - run: npm ci
      - run: npm run build
        env:
          VITE_API_URL: ${{ vars.VITE_API_URL }}
      - uses: actions/configure-pages@v6
      - uses: actions/upload-pages-artifact@v5
        with:
          path: ./dist
      - id: deployment
        uses: actions/deploy-pages@v5

Рақамҳои версияи амалҳо (@v7, @v5…) бо мурури замон иваз мешаванд — пеш аз нусха кардан бо мисоли ҷорӣ дар vite.dev/guide/static-deploy муқоиса кунед. Ин муқаррарӣ аст: дастурҳои деплойро ҳамеша тозаашро кушодан лозим аст, на ба хотира (ва ба хотираи ЗС) такя кардан.

Чӣ интихоб кардан

VercelGitHub Pages
Нишонӣлоиҳа.vercel.appлогин.github.io/репозиторий/
Танзимбо мушак, дар 3 дақиқафайли workflow + base
Тағйирёбандаҳои муҳитдар панели лоиҳаVariables дар танзимоти репозиторий
Пешнамоиши шохаҳоҳа, худкорне
base лозим астнеҳа, /номи-репозиторий/
Репозиторийи хусусӣмешавадройгон — танҳо оммавӣ

Барои курс: лоиҳаи аввал — дар Vercel, дуюм — дар GitHub Pages. Ҳамин тавр шумо ҳарду равишро месанҷед, ва дар портфолио ду истиноди зинда мешавад.

Windows ва macOS

Фармонҳои Git ва npm яксонанд. Фарқ дар терминал: дар Windows PowerShell ё Git Bash, дар macOS — «Терминал»-ро истифода баред. Агар Git дар Windows бо «LF will be replaced by CRLF» шикоят кунад — ин огоҳӣ дар бораи гузариши сатрҳост, ба ҷамъбаст халал намерасонад. Ва чизи асосӣ барои ҳарду система: сайтро пас аз деплой санҷед — истинодро дар реҷаи инкогнито ва аз телефон кушоед.

Муфассалтар хонед: vite.dev — Деплойи сайти статикӣ, Vercel — Vite

Амал: мустаҳкам мекунем

ВАЗИФАИ 8.1

Роҳ ба файлҳо дар GitHub Pages

миёна

Ду функсия нависед. getBase(repoName) қимати base-ро барои Vite бармегардонад: "/" + ном + "/", ва барои сайти «корбарӣ» (ном бо .github.io тамом мешавад) — танҳо "/". assetUrl(base, path) базаро ва роҳи файлро чунон мечаспонад, ки байни онҳо дақиқан як хати моил бошад (дар path хати моил дар аввал метавонад бошад ва метавонад набошад).

Таҳрир кардан мумкин аст · Ctrl + Enter
function getBase(repoName) {
  // коди шумо
}

function assetUrl(base, path) {
  // коди шумо
}

console.log(getBase("my-shop"));
console.log(getBase("komilovsg.github.io"));
console.log(assetUrl("/my-shop/", "img/logo.png"));
console.log(assetUrl("/my-shop/", "/img/logo.png"));
console.log(assetUrl("/", "/favicon.svg"));
Натиҷаи интизоршаванда
/my-shop/
/
/my-shop/img/logo.png
/my-shop/img/logo.png
/favicon.svg
Ишора 1

Барои getBase: if (repoName.endsWith(".github.io")) return "/"; — бозгашти барвақтӣ, баъд return `/${repoName}/`;.

Ишора 2

Барои assetUrl хати моили аввали роҳро хориҷ кунед: const cleanPath = path.startsWith("/") ? path.slice(1) : path; — ва base + cleanPath-ро бичаспонед (база ҳамеша бо хати моил тамом мешавад).

ВАЗИФАИ 8.2

Ташхис: пас аз деплой чӣ вайрон шуд

осон

Чор вазъият пас аз деплой ва чор сабаб. Мутобиқ кунед: дар массиви answers барои ҳар вазъият бо тартиб ҳарфи сабабро нависед.

Таҳрир кардан мумкин аст · Ctrl + Enter
// Вазъиятҳо:
// 1. Дар маҳал расми logo.png намоён аст, дар Vercel — не. Дар код "./Logo.png" навишта шудааст.
// 2. Сайт кушода шуд, аммо дархостҳо ба нишонии "undefined/products" мераванд.
// 3. GitHub Pages: саҳифа холӣ, дар консол 404 ба /assets/index-xxx.js.
// 4. Тағйирёбандаро ба панели Vercel илова кардем, аммо сайт қимати кӯҳнаро нишон медиҳад.
//
// Сабабҳо:
// A. base дар vite.config.js муайян нашудааст.
// B. Ҳарфи калон ва хурд дар номи файл мувофиқат намекунад.
// C. Тағйирёбандаи муҳит ба хостинг илова нашудааст.
// D. Пас аз илова кардани тағйирёбанда Redeploy накарданд.

const answers = [/* "?", "?", "?", "?" */];
console.log(answers.join(", "));
Натиҷаи интизоршаванда
B, C, A, D
Ишора 1

Вазъияти 3 — дар бораи GitHub Pages ва «файл дар реша ёфт нашуд»: кадом танзим барои зерпапка масъул аст?

Ишора 2

Дар вазъиятҳои 2 ва 4 сухан дар бораи тағйирёбандаҳост, аммо дар 2 қимат тамоман нест, ва дар 4 — қимат ҳаст, танҳо кӯҳна (аз нав ҷамъ нашуд).

09 Блоки ЗС: ревьюи код ва README

Имрӯз ЗС дар ду нақш кор мекунад: ревьюер (кодатонро мехонад ва мушкилотро пай мебарад) ва ёрдамчии матнҳо (README ва тавсифи лоиҳа барои портфолио). Дар ҳарду ҳолат маҳорати асосӣ на «ҷавоб гирифтан», балки хубро аз бад ҷудо кардан аст: ЗС ҳам муфид, ҳам зарарнокро бо боварӣ маслиҳат медиҳад.

Қоидаҳои курс, ки дар ин ҷо махсусан муҳиманд

1. Аввал 15 дақиқа худатон: аз рӯи чек-лист гузаред ва мулоҳизаҳои худро сабт кунед. 2. Танҳо баъд ревью металабед — ва бо рӯйхати худатон муқоиса кунед. 3. Таҳрироте, ки бо суханони худатон шарҳ дода наметавонед, қабул накунед. 4. Пас аз ҳар таҳрир кодро иҷро кунед: рафтор набояд тағйир ёбад. 5. README ва матни портфолиоро — бо суханони худатон бознависед: аз ибораҳои қолабӣ матни ЗС фавран намоён аст.

Ревью аз рӯи чек-лист: бад ва хуб

Формулаи промпти курс: контекст → вазифа → маҳдудиятҳо → формати ҷавоб → санҷиш.

кодамро беҳтар кун
Ман JavaScript меомӯзам: функсияҳо, массивҳо, объектҳо, DOM ва fetch-ро медонам. Дар зер функсия аз лоиҳаи хурди ман «феҳристи маҳсулот». Онро аз рӯи чек-лист санҷ: 1) номҳо; 2) андозаи функсия; 3) такрор; 4) бозгашти барвақтӣ; 5) рақамҳои ҷодуӣ; 6) ҷудо кардани мантиқ ва намоиш; 7) шарҳҳо. Формати ҷавоб: рӯйхати рақамгузорӣшудаи мулоҳизаҳо «банди чек-лист → дар куҷои код → мушкил дар чист → барои чӣ муҳим аст». Танҳо мулоҳизаҳо, бе аз нав навиштани тамоми код. Китобхонаҳо ва технологияҳои навро пешниҳод накун, рафтори функсияро тағйир надеҳ. Агар аз рӯи банд ҳама хуб бошад — ҳамин тавр нависед. Код: [функсияро гузоред]

Чаро промпти дуюм беҳтар кор мекунад: ЗС сатҳи шуморо медонад, рӯйхати мушаххаси меъёрҳоро гирифт, он чизеро, ки напурсидаанд, «беҳтар» карда наметавонад, ва ҷавобро шумо фавран бо рӯйхати худатон муқоиса карда метавонед.

Филтри маслиҳатҳо: қабул ё рад кардан

Ҳар маслиҳати ЗС аз панҷ савол мегузарад. Як «не» кофист — ва маслиҳатро қабул намекунем (ё мегузорем):

СаволАгар «не»
1. Ман таҳрирро бо суханони худам шарҳ дода метавонам?Қабул намекунем — то нафаҳмем
2. Рафтори код яксон монд?Ин аллакай рефакторинг нест: вазифаи алоҳида ва commit-и алоҳида
3. Ин мушкили воқеиро ҳал мекунад (банди чек-лист ҳаст)?Рад мекунем: «беҳтар кардан барои беҳтар кардан»
4. Метод ё китобхона вуҷуд дорад?Дар MDN месанҷем. ЗС гоҳо методҳои вуҷуднадоштаро меандешад
5. Код соддатар шуд, на мураккабтар?Рад мекунем: вобастагиҳои зиёдатӣ, паттернҳо ва «доно» якқатораҳо
Одатан қабул кардан арзанда
  • Рақами ҷодуиро ба собит баровардан
  • x, data-ро ба чизи фаҳмо иваз кардан
  • Коди мурда ва console.log-и ислоҳиро хориҷ кардан
  • if-ҳои дарунҷойгирро бо return-и барвақтӣ иваз кардан
  • Порчаи такроршавандаро ба функсия баровардан
Одатан рад кардан арзанда
  • «Китобхона / TypeScript / Redux-ро пайваст кунед» барои як функсия
  • Шарҳ ба ҳар сатр
  • Номҳо ба дарозии 40 аломат
  • «Ҳамаро ба try/catch печонед»
  • Калид ё парол «барои қулайӣ» бевосита дар код
  • Методе, ки дар MDN нест
Маслиҳати хатарнок: тағйири хомӯшонаи рафтор

Таҳрирҳои маккортарин мисли «беҳтар кардани хонишпазирӣ» менамоянд, аммо натиҷаро каме тағйир медиҳанд: >= ба > табдил мешавад, санҷиши массиви холӣ нест мешавад. Онҳоро танҳо иҷро дар қиматҳои сарҳадӣ мегирад — мисли вазифаи 5.4.

Амал: ревью бо ЗС

Дар зер — ҷавобҳои дар руҳ ҳақиқии ревьюи ЗС. Вазифаи шумо — ревьюери ревьюер будан.

ВАЗИФАИ 9.1

Қабул ё рад кардан

миёна

ЗС функсияро санҷид ва ҳашт маслиҳат дод. Барои ҳар кадом ба массиви verdicts нависед: "A" (қабул кардан) ё "R" (рад кардан). Ба панҷ саволи боло такя кунед.

Таҳрир кардан мумкин аст · Ctrl + Enter
/*
function calcTotal(items, promo) {
  let total = 0;
  for (const item of items) {
    total += item.price * item.qty;
  }
  if (promo === "NAVRUZ") {
    total = total * 0.85;
  }
  if (total > 300) {
    total = total + 0;
  } else {
    total = total + 25;
  }
  return total;
}
*/

// Маслиҳатҳои ЗС:
// 1. Рақамҳои 0.85, 300 ва 25-ро ба собитҳои номдор бароред.
// 2. Давраи for...of-ро бо reduce иваз кунед — reduce ҳамеша аз давраҳо беҳтар аст.
// 3. Сатри «total = total + 0» ҳеҷ кор намекунад — онро хориҷ кунед.
// 4. Болои ҳар сатри функсия шарҳ илова кунед.
// 5. total-ро ба finalTotalAmountWithPromoAndDeliveryCalculated иваз кунед.
// 6. Ҳисоб аз рӯи промокодро ба функсияи алоҳидаи applyPromo бароред.
// 7. Тамоми бадани функсияро ба try/catch бипечонед, барои ҳолати хато.
// 8. lodash-ро пайваст кунед, то нархҳоро ҷамъ кунад.

const verdicts = [/* "A" ё "R" барои маслиҳатҳои 1–8 */];
console.log(verdicts.join(","));
Натиҷаи интизоршаванда
A,R,A,R,R,A,R,R
Ишора 1

Он чиро қабул мекунем, ки кодро бе тағйири рафтор фаҳмотар мекунад: собитҳо (1), сатри мурда (3), функсияи алоҳида (6).

Ишора 2

Таҳлили радкуниҳо. 2 — «ҳамеша беҳтар» нодуруст аст: давра дар ин ҷо бадтар нахонда мешавад. 4 — садо ба ҷои фоида. 5 — номи 50 аломатӣ аз total бадтар аст. 7 — try/catch бе сабаб хатоҳоро пинҳон мекунад. 8 — вобастагӣ барои як маҷмӯъ.

ВАЗИФАИ 9.2

Қабул, рад ё санҷидан

душвор

Ревьюи дуюм, нозуктар. Акнун се ҳукм: "A" — фавран қабул кардан (фаҳмотар, рафтор ҳамон); "T" — муфид, аммо рафторро тағйир медиҳад: бо вазифаи алоҳида бо тестҳо, на дар рефакторинг; "R" — рад кардан (лозим нест, зарарнок ё андешидашуда).

Таҳрир кардан мумкин аст · Ctrl + Enter
/*
function getCheapProducts(products) {
  const result = [];
  for (let i = 0; i < products.length; i++) {
    if (products[i].price < 20) {
      result.push(products[i]);
    }
  }
  return result;
}
*/

// Маслиҳатҳои ЗС:
// 1. Давраро бо products.filter(...) иваз кунед, ва рақами 20-ро ба собити MAX_PRICE бароред.
// 2. Методи дарунсохти products.filterByPrice(20)-ро истифода баред — он ҳамонро тезтар мекунад.
// 3. «<»-ро ба «<=» иваз кунед: «то 20 сомонӣ» мантиқитар аст, ки сарҳад дохил шавад.
// 4. Нархҳоро аз сервер бор кунед, калидро бевосита ба функсия навишта: const KEY = "sk_live_...".
// 5. result-ро ба cheapProducts иваз кунед.
// 6. Пеш аз бозгардонидан маҳсулотро аз рӯи нарх бо тартиби афзоиш мураттаб кунед.
// 7. TypeScript ва Redux илова кунед — ҳамин тавр функсия боэътимодтар мешавад.

const verdicts = [/* "A", "T" ё "R" барои маслиҳатҳои 1–7 */];
console.log(verdicts.join(","));
Натиҷаи интизоршаванда
A,R,T,R,A,T,R
Ишора 1

Методи маслиҳати 2-ро дар MDN санҷед: массивҳо filterByPrice надоранд. Ин ихтироъ аст (R). Калид дар код (4) — ошкор шудани сир (R).

Ишора 2

Маслиҳатҳои 3 ва 6 — дар бораи хониши код нестанд: сарҳади 20 ба натиҷа меафтад, ва тартиби маҳсулот тағйир меёбад. Шояд ҳамин лозим бошад — аммо ин қарори соҳиби маҳсулот аст, commit-и алоҳида. Барои ҳамин «T».

ВАЗИФАИ 9.3

Рефакторинги ЗС-ро месанҷем

миёна

ЗС функсияи интиқолро ба як сатр «содда кард». Ӯ қасам мехӯрад, ки рафтор ҳамон аст. Санҷед: аз рӯи рӯйхати вурудҳо гузаред, ҳарду версияро даъват кунед ва танҳо он вурудҳоро чоп кунед, ки ҷавобҳо фарқ мекунанд, бо формати маблағ isMember: буд → шуд (масалан, 100 false: 25 → 0).

Таҳрир кардан мумкин аст · Ctrl + Enter
function getShipping(sum, isMember) {
  if (isMember) return 0;
  if (sum >= 300) return 0;
  return 25;
}

function getShippingAI(sum, isMember) {
  return isMember || sum > 300 ? 0 : 25;
}

const inputs = [[100, false], [300, false], [300, true], [500, false], [0, true], [299.99, false]];

// коди шумо: давра аз рӯи inputs ва муқоиса
Натиҷаи интизоршаванда
300 false: 0 → 25
Ишора 1

for (const [sum, isMember] of inputs) — деструктуркунии ҷуфт. Дар дохил getShipping(sum, isMember) ва getShippingAI(sum, isMember)-ро муқоиса кунед.

Ишора 2

Агар баробар набошанд — console.log(`${sum} ${isMember}: ${before} → ${after}`). Хатои ЗС: коди аслӣ интиқолро аз 300 аз ҷумла ройгон ҳисоб мекард, «соддакардашуда» бошад — танҳо аз 300 зиёд.

README ва матн барои портфолио бо ЗС

README — чизи аввале аст, ки рекрутер дар саҳифаи репозиторий мебинад. Хуб аст, вақте ки он ба чор савол ҷавоб медиҳад: ин чист, бо чӣ сохта шудааст, чӣ тавр оғоз кардан, дар куҷо дидан. ЗС зуд скелетро ҷамъ мекунад, аммо қоида ҳаст: ЗС танҳо далелҳоеро мегирад, ки шумо ба ӯ додаед. Вагарна ӯ функсияҳоеро, ки нестанд, мекашад.

README барои сайти ман бинавис
Ёрӣ деҳ, ки README барои лоиҳаи таълимӣ нависем. Далелҳо (танҳо онҳоро истифода бар, чизе наандеш): ном — «Феҳристи маҳсулот»; чӣ кор мекунад — маҳсулотро аз dummyjson.com нишон медиҳад, ҷустуҷӯ аз рӯи ном ва саҳифабандӣ ҳаст; стек — HTML, CSS, JavaScript, Vite; оғоз — npm install, баъд npm run dev; демо — [истинод]. Сохтор: ин чист (2 ҷумла) → стек → чӣ тавр оғоз кардан (фармонҳо дар блоки код) → скриншот (ҷойро барои расми ./screenshot.png гузор) → минбаъд чӣ (3 ғоя). Оҳанг оддӣ, бе калимаҳои баландпарвоз монанди «инқилобӣ». Агар далелҳо намерасанд — савол деҳ, наандеш. Санҷиш: ҳамаи фармонҳо дар матн бояд барои лоиҳаи Vite воқеӣ бошанд.
4 ҷумла дар бораи лоиҳаи ман барои портфолиои фронтенд-таҳиягари навкор нависед: кадом вазифаро ҳал мекунад; ман худам чӣ кардам (ҷустуҷӯ, саҳифабандӣ, ҳолатҳои боркунӣ ва хато); стек; истинод ба демо [истинод]. Шахси якум, бе оби зиёдатӣ ва клишеҳо монанди «таҳиягари ҳавасманд». Ду вариант бо дарозии гуногун нишон деҳ.

Дар матни ЗС чиро санҷидан лозим

  • Функсияҳо ва технологияҳои андешидашуда. «Авторизатсия», «пойгоҳи додаҳо», «фарогирии тестҳо 95%» — агар дар лоиҳа нест, хат мезанем.
  • Фармонҳо. Ҳар яки аз README-ро дар папкаи тоза иҷро кунед: npm install, npm run dev. Кор мекунад — мегузорем.
  • Скриншот ва истинод ба демо — худатон мегузоред, ЗС онҳоро намедонад.
  • Ибораҳои қолабӣ («ин лоиҳа маҳз … мебошад», «ҳалли муосир») — бо суханони худатон бознависед. Рекрутер овози одамро мешунавад, на шабакаи асабиро.
  • Ростқавлӣ. Чӣ худатон кардед, ва чӣ бо ёрии ЗС — бевосита гуфтан мумкин аст. Касе интизор нест, ки шумо бе ёридиҳандагон навиштаед; интизоранд, ки шумо кодро мефаҳмед.

Амал: README бе андеша

ВАЗИФАИ 9.4

Андешаҳоро дар README ёбед

осон

Далелҳо дар бораи лоиҳа: HTML, CSS, JavaScript, Vite; маълумот аз dummyjson.com гирифта мешавад; ҷустуҷӯ ва саҳифабандӣ ҳаст; нишонагузорӣ мутобиқшаванда; вуруд ба ҳисоб, пойгоҳи додаҳо ва тестҳо нест. ЗС ҳафт изҳорот барои README навишт. Ба массиви invented рақамҳои андешидашуда-ро нависед (бо тартиби афзоиш).

Таҳрир кардан мумкин аст · Ctrl + Enter
// Нусхаи пешакии README аз ЗС:
// 1. Ҷустуҷӯ аз рӯи номи маҳсулот ва баровардани саҳифагӣ.
// 2. Вуруд тавассути ҳисоби Google.
// 3. Оғоз: npm install, баъд npm run dev.
// 4. Маълумот дар пойгоҳи PostgreSQL нигоҳ дошта мешавад.
// 5. Нишонагузории мутобиқшаванда: сайтро дар телефон кушодан қулай аст.
// 6. Фарогирии автотестҳо — 95%.
// 7. Маълумот дар бораи маҳсулот аз dummyjson.com гирифта мешавад.

const invented = [/* рақамҳо */];
console.log(invented.join(", "));
Натиҷаи интизоршаванда
2, 4, 6
Ишора 1

Ҳар изҳоротро бо рӯйхати далелҳо муқоиса кунед: вуруд, пойгоҳи додаҳо ва тестҳо дар лоиҳа нестанд.

Ишора 2

Андешаҳо — вуруд тавассути Google, PostgreSQL ва 95% фарогирӣ. Чор банди боқимонда ҳақиқатанд.

10 Амал дар дарс: ревьюи ҳамсоя ва деплойи гурӯҳ

Нимаи дуюми дарс — гурӯҳӣ: шумо лоиҳаи ҳамсояро месанҷед ва беҳтар мекунед, баъд тамоми гурӯҳ лоиҳаҳои худро ба интернет мегузорад. Ин маҳз ҳамон чизест, ки дар гурӯҳи ҳақиқӣ рух медиҳад: code-review → таҳрирҳо → релиз.

ВақтЧӣ мекунем
10 дақТаҳлили мушкилоти маъмул дар проектор, такрори чек-лист
10 дақҚисми A: ревьюи лоиҳаи ҳамсоя аз рӯи чек-лист (аввал худатон, бе ЗС)
25 дақҚисми B: рефакторинг аз рӯи мулоҳизаҳо — дар шохаи алоҳида
30 дақҚисми C: деплойи ҳамаи лоиҳаҳои гурӯҳ
10 дақҚисми D: README бо ЗС ва рӯйхати умумии истинодҳо
5 дақХулоса: лоиҳа пеш аз ва пас аз чӣ қадар хол гирифт

Қисми A. Ревьюи лоиҳаи ҳамсоя (дар ҷуфтҳо)

  1. Истиноди репозиторийҳоро мубодила кунед. Лоиҳаи ҳамсояро clone кунед: git clone истинод, баъд npm install ва npm run dev. Боварӣ ҳосил кунед, ки он оғоз мешавад.
  2. Чек-листи чопӣ-ро (қисми 11) кушоед. Аз рӯи 12 банд гузаред ва дар сутуни «То» нишон гузоред.
  3. 5–8 мулоҳиза-ро бо як формат сабт кунед: файл:сатр — банди № — чӣ нодуруст аст ва барои чӣ — чӣ тавр ислоҳ кардан. Мисол: src/cart.js:14 — банди 5 — рақами 300 бе ном, нофаҳмо аст, ки ин остонаи интиқол аст — ба FREE_DELIVERY_FROM баровардан.
  4. Мулоҳизаҳо бояд хушмуомила ва мушаххас бошанд: «функсияи calc нофаҳмо номгузорӣ шудааст» — бад; «дар calc t-ро ба total иваз кунед, то намоён шавад, ки ҷамъ мекунем» — хуб. Кодро интиқод мекунем, на одамро.
  5. Мулоҳизаҳоро бо овоз муҳокима кунед: муаллиф ҳақ дорад розӣ нашавад, агар фаҳмонад, ки барои чӣ.

Қисми B. Рефакторинг аз рӯи мулоҳизаҳо

  1. Муаллиф шоха эҷод мекунад: git switch -c refactor/clean-code.
  2. Аз рӯи мулоҳизаҳо яктоӣ мегузарад. Пас аз ҳар кадом: иҷро → ҳама мисли пештара кор мекунад → git commit -m "extract delivery constants" (паём — аз рӯи қоидаҳои дарси 19).
  3. Санҷиши рафтор: барномаро кушоед ва ҳамон сенарияҳоро, ки пеш аз таҳрирҳо, гузаред (ҷустуҷӯ, саҳифабандӣ, хатои шабака). Чизе тағйир ёфт — бозгашт: git restore ..
  4. Дар охир: npm run build бе хато. Баъд git push-и шоха.
  5. Чек-листро такроран гузаред, сутуни «Пас»-ро пур кунед. Ҳадаф — на камтар аз 10 аз 12.

Қисми C. Деплойи ҳамаи лоиҳаҳои гурӯҳ

  1. Лоиҳаи 1 → Vercel аз рӯи қадамҳои қисми 08. Вақти ҳадаф — 10 дақиқа. Нашуд? Логи ҷамъбастро хонед: хато қариб ҳамеша дар сатрҳои охирин нишон дода шудааст.
  2. Лоиҳаи 2 → GitHub Pages: base, workflow, Settings → Pages. Онҳое, ки зудтар тамом карданд, ба ҳамсояҳо навбатӣ кумак мекунанд — шарҳ додан, на ба ҷои дигаре пахш кардан.
  3. Санҷиши истинод: дар реҷаи инкогнито ва дар телефон кушоед, дар DevTools → Console хатои сурх набояд бошад, дар Network — ягон 404 нест.
  4. Ҳамаи истинодҳо ба ҷадвали умумии гурӯҳ ворид мешаванд (формат: ном, лоиҳа, истинод ба сайт, истинод ба репозиторий).

Қисми D. README бо ЗС

  1. Далелҳо-ро дар бораи лоиҳа омода кунед: чӣ кор мекунад, стек, фармонҳои оғоз, истинод ба демо.
  2. Аз ЗС хоҳиш кунед, ки README-ро аз рӯи промпти қисми 09 ҷамъ кунад.
  3. Аз рӯи рӯйхати «Чиро санҷидан» санҷед: андешаҳоро хат занед, фармонҳоро иҷро кунед, скриншот ва истинод илова кунед, ибораҳои қолабиро бознависед.
  4. README.md-ро ба реша commit кунед ва фиристед.
Тайёр аст, вақте ки

Лоиҳа дорад: чек-лист ≥ 10/12, истиноди зинда, README бо скриншот, .env.example ва дар таърих сирр нест. Натиҷаро ба ҳамсоя ва муаллим нишон диҳед.

11 Чек-листи сифати код (версияи чопӣ)

Як чек-лист барои тамоми гурӯҳ: аз рӯи он шумо лоиҳаҳои худ, лоиҳаҳои ҳамсояҳо ва (баъдтар) лоиҳаи ниҳоиро месанҷед. Саҳифаро чоп кунед (Ctrl + P дар Windows, Cmd + P дар macOS) — панел ва ишораҳо ҳангоми чоп пинҳон мешаванд, ҷадвал мемонад. Ё онро ба PDF нигоҳ доред.

Лоиҳа: ____________________

Муаллиф: ____________________

Ревьюер: ____________________

Сана: ______________

№БандЧӣ тавр санҷиданТоПас
Код
1Номҳо мегӯянд, ки ин чистa, x1, data, temp нест; булӣ — is/has/can; функсияҳо — феълҳо☐☐
2Функсияҳои хурдҲар кадом як чизро мекунад, дар ном «ва» нест, дар экран ҷо мешавад☐☐
3DRYБлокҳои нусхашуда нестанд; такроршаванда ба функсия ё маълумот баровардашуда☐☐
4Бозгашти барвақтӣДарунҷойгирӣ аз 2–3 сатҳ чуқуртар нест, else-и зиёдатӣ пас аз return нест☐☐
5СобитҳоРақамҳо ва сатрҳои ҷодуӣ нестанд — ҳама дар UPPER_SNAKE_CASE дар боло аз файл☐☐
6Мантиқ ҷудо аз намоишФунксияҳои ҳисобкунӣ ба DOM даст намезананд ва ба консол чоп намекунанд☐☐
7Шарҳҳо«Барои чӣ»-ро шарҳ медиҳанд; коди шарҳшуда ва шарҳҳои такрор нестанд☐☐
8Тозагӣconsole.log-и ислоҳӣ, тағйирёбандаҳо ва функсияҳои истифоданашаванда, var нестанд☐☐
Лоиҳа
9СирҳоКалидҳо дар код ва таърих нестанд; .env.local дар .gitignore; .env.example ҳаст☐☐
10Ҷамъбастnpm run build бе хато ва огоҳӣ мегузарад☐☐
11READMEИн чист, стек, чӣ тавр оғоз кардан, скриншот, истинод ба демо☐☐
12Истиноди зиндаДар инкогнито ва дар телефон кушода мешавад; дар Console хато нест, дар Network 404 нест☐☐

Ҳамагӣ: пеш аз рефакторинг ____ / 12, пас аз он ____ / 12.

Се мулоҳизаи асосии ревьюер:

1. ______________________________

2. ______________________________

3. ______________________________

Чӣ тавр баҳо додан

Банд танҳо дар сурате ҳисоб мешавад, ки дар тамоми лоиҳа иҷро шудааст, на дар як файл. 10–12 хол — лоиҳа барои нишон додан омода аст; 7–9 — такмил лозим аст; камтар аз 7 — аз бандҳои 1, 5 ва 8 оғоз кунед: онҳо аз ҳама соддатаранд ва таассуротро аз ҳама бештар беҳтар мекунанд.

12 Вазифаи хонагӣ

Вазифа: лоиҳаи хурди 2-ро рефакторинг кунед, ду лоиҳаро деплой кунед, README-ро ороиш диҳед ва истинодҳоро фиристед. Натиҷаи дарс — чек-листи пуршудаи сифати код ва истинодҳои зинда ба лоиҳаҳо.

  1. То-ро баҳо диҳед. Лоиҳаи хурди 2-ро аз рӯи чек-листи қисми 11 пеш аз ҳар таҳрир гузаред. Натиҷаро (X аз 12) ва рӯйхати вайронкуниҳоро сабт кунед.
  2. Рефакторинг кунед. Шохаи refactor/clean-code-ро эҷод кунед. На камтар аз панҷ commit-и бомаъно — ҳар кадом дар бораи як таҳрир («rename cart variables», «extract delivery constants», «split render from calc»). Рафтори барнома тағйир намеёбад.
  3. Пас-ро баҳо диҳед. Чек-листро такрор кунед. Ҳадаф — на камтар аз 10 аз 12. Шохаро бо усули оддӣ ба асосӣ ҷамъ кунед (тавассути PR, мисли дарси 19).
  4. Ду лоиҳаро деплой кунед. Лоиҳаи хурди 2 — дар Vercel; як лоиҳаи дигар (лоиҳаи хурди 1 ё ҳар кадом дигар) — дар GitHub Pages. Ҳарду истинод бояд бе хато дар консол кушода шаванд.
  5. Сирҳо ва муҳит. Дар ҳарду репозиторий .env.example ҳаст, калидҳои воқеӣ нестанд, тағйирёбандаҳо (агар бошанд) дар хостинг муайян шудаанд.
  6. README. Дар ҳар репозиторий: ин чист, стек, чӣ тавр оғоз кардан, скриншот, истинод ба демо, «минбаъд чӣ». Нусхаи пешакиро бо ЗС кардан мумкин аст, вале бо суханони худатон бознависед ва ҳамаи фармонҳоро санҷед.
  7. Матн барои портфолио. 3–4 ҷумла дар бораи лоиҳаи хурди 2: вазифа, худатон чӣ кардед, стек, истинод.

Чӣ супурдан лозим

  • Истинодҳо ба ду репозиторий ва ду истиноди зинда ба сайтҳо.
  • Чек-листи пуршуда (сутунҳои «То» ва «Пас») бо ҳисоб.
  • Дафтари рефакторинг: ҷадвал ҳадди аққал аз панҷ сатр — «банди чек-лист → чӣ тағйир додем → номи commit».
  • Матн барои портфолио (дар README ё дар файли алоҳида).

Чӣ тавр баҳо медиҳем (0–10)

ЧӣХолҳо
Рефакторинг: чек-лист пас аз он ≥ 10 аз 12, рафтор тағйир наёфтааст3
Деплой: ҳарду истинод кушода мешаванд, дар консол хато ва 404 нест3
README: ҳамаи бахшҳо, скриншот, фармонҳои корӣ, функсияҳои андешидашуда нестанд2
Сирҳо ва .env.example; ҷамъбаст мегузарад1
Дафтари рефакторинг ва баҳои ростқавлонаи «То» (≥ 5 commit-и бомаъно)1

✓ Варақаи кӯмакии дарс

  • Номҳо: тағйирёбанда — исм, функсия — феъл, булӣ — is/has/can, собит — UPPER_SNAKE. Бе data, temp, x1.
  • Функсия як чизро мекунад. «Ва» дар тавсиф — сабаби тақсим кардан. Нишондиҳанда — як экран.
  • Бозгашти барвақтӣ: аввал ҳолатҳои бадро мебуранд if (...) return ...;, мантиқи асосӣ ҳамвор мемонад, else пас аз return лозим нест.
  • DRY: бори сеюм такрор шуд — ба функсия ё маълумот бароред. Он чиро, ки тасодуфан монанд аст, муттаҳид накунед.
  • Рақамҳои ҷодуӣ → собитҳои номдор дар боло аз файл, воҳидҳои ченак дар ном.
  • Мантиқ ≠ намоиш: ҳисоб додаҳоро бармегардонад, render нишон медиҳад, коркунанда мечаспонад.
  • Шарҳ ба «барои чӣ» ҷавоб медиҳад, на «чӣ». Коди шарҳшударо — хориҷ кардан (Git ба ёд дорад).
  • Рефакторинг шаклро тағйир медиҳад, на рафторро: тест → қадами хурд → иҷро → commit. Ё рефакторинг мекунем, ё хато ислоҳ мекунем — на якбора.
  • Ҷамъбаст: npm run build → dist/, санҷиш — npm run preview. dist-ро ба Git намегузорем. Ҳарфи калон ва хурди номҳои файлҳо бояд мувофиқат кунад.
  • Тағйирёбандаҳои муҳит: import.meta.env.VITE_*, қиматҳо — сатрҳо, пас аз таҳрири .env аз нав оғоз. .env.local — дар .gitignore, .env.example — ба репозиторий. Дар браузер сирр нест.
  • Vercel: Import-и репозиторий → preset Vite → тағйирёбандаҳо → Deploy; пас аз иваз кардани тағйирёбандаҳо — Redeploy. GitHub Pages: base: "/репозиторий/" + Settings → Pages → GitHub Actions + workflow.
  • Ревьюи ЗС: мулоҳизаҳоро аз рӯи чек-лист мепурсем, на «беҳтар кун». Маслиҳатро дар сурате қабул мекунем, ки онро мефаҳмем, рафтор ҳамон аст, мушкил воқеӣ аст, метод вуҷуд дорад ва код соддатар аст. README — танҳо аз рӯи далелҳо, бо суханони худатон бознависед.