در این فصل چه میسازی#
تا امروز هر عنصرِ صفحه را خودت با دست مینوشتی؛ از این فصل، صفحه یاد میگیرد خودش را از روی داده بسازد. یک کارتِ «مهارتهای من» میسازی که فهرستش از یک آرایهٔ JavaScript میآید: برای هر مهارت، کدِ تو یک <li> میسازد و به صفحه میچسباند. یک فرمِ کوچک هم دارد: هر مهارتِ تازهای که تویش بنویسی، هم به آرایه اضافه میشود و هم بیدرنگ روی صفحه ظاهر میشود.

آخر این فصل میتوانی:
- چند مقدار را با هم در یک array نگه داری و با index و
lengthوpushکار کنی - با
for...of(وforEach) یک کار را برای تکتکِ عضوهای آرایه تکرار کنی - با
createElementوappendعنصرِ تازه در DOM بسازی - الگوی «اول خالی کن، بعد از نو بساز» را برای نمایشِ دوبارهٔ فهرست بهکار ببری
قبل از شروع#
- از فصل ۳:
document.querySelectorوtextContent. - از فصل ۶: فرم در JavaScript —
value، رویدادsubmit،preventDefaultوif/else. - از فصل ۲:
constو template literal.
مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.
۱. array: یک فهرست در یک متغیر#
اینهمه ترم گذشته و مهارتهایت دیگر در یک متغیر جا نمیشوند. let و const هر بار فقط یک مقدار نگه میداشتند؛ array یک ردیف مقدار را با هم نگه میدارد:
const skills = ['HTML', 'CSS', 'flexbox', 'grid'];
کروشه یعنی «این یک آرایه است» و عضوها با ویرگول جدا میشوند. برای آزمایش، این خطها را در تبِ JS زیرِ آرایه بنویس و خروجی را با F12 در console ببین — از خودِ تبِ JS بنویس، نه با تایپ در console؛ خطِ فرمانِ console به صفحهٔ اصلی وصل است، نه به پیشنمایشِ آزمایشگاه:
console.log(skills[0])— جوابش'HTML'است. به این شمارهها index میگویند و از صفر شروع میشوند.console.log(skills.length)— تعدادِ عضوها را میدهد.skills.push('JavaScript')و بعدconsole.log(skills)— یک عضو به تهِ آرایه اضافه شد.
Checkpoint. قبل از ادامه، جواب بده: اگر skills.length چهار باشد، آخرین عضو چه index ی دارد؟ (جواب: ۳ — چون شمارش از صفر شروع میشود.)
۲. for...of: برای هر عضو، یک بار#
آرایه بدونِ حلقه فقط یک انبار است. for...of یعنی «برای هر عضوِ این آرایه، این کار را بکن»:
for (const skill of skills) {
console.log(skill);
}
مثل یک جمله بخوانش: «برای هر skill از skills…». داخلِ آکولاد، skill هر بار یکی از عضوهاست — بارِ اول 'HTML'، بارِ دوم 'CSS'، تا آخر. اگر آرایه خالی باشد، حلقه صفر بار اجرا میشود، بدونِ هیچ خطایی.
✅ چک کن: در console، مهارتها یکییکی زیرِ هم چاپ میشوند.
۳. از آرایه تا صفحه: createElement و append#
querySelector فقط عنصرهای موجود را پیدا میکند؛ برای فهرستِ ما باید عنصرِ تازه ساخت. دستورش سه قدم دارد: بساز، پُر کن، بچسبان:
const list = document.querySelector('#skills-list');
for (const skill of skills) {
const item = document.createElement('li');
item.textContent = skill;
list.append(item);
}
createElement('li') یک <li> میسازد که هنوز هیچجای صفحه نیست — مثل آجری که هنوز در دیوار نگذاشتهای. textContent متنش را میگذارد و append آن را به تهِ عنصرِ list میچسباند؛ حالا واقعاً روی صفحه است.
✅ چک کن: چهار مهارت زیرِ تیتر ظاهر شدند. حالا یک عضو به آرایه اضافه کن و ببین فهرست هم بلندتر میشود — صفحه دارد از روی داده ساخته میشود.
💡 نکته: «داده در آرایه، نمایش با حلقه» هستهٔ هر اپِ واقعی است: فیدِ هر شبکهٔ اجتماعی همین است — یک آرایهٔ پست، و حلقهای که برای هرکدام یک کارت میسازد.
۴. دکمهٔ «افزودن» و باگِ فهرستِ دوقلو#
حالا فرم را زنده کنیم: مهارتِ تازه به آرایه push شود و فهرست دوباره ساخته شود. اولین تلاش — همان حلقه را داخلِ listener هم اجرا میکنیم:
const form = document.querySelector('#skill-form');
const input = document.querySelector('#skill-input');
form.addEventListener('submit', function (event) {
event.preventDefault();
skills.push(input.value);
for (const skill of skills) {
const item = document.createElement('li');
item.textContent = skill;
list.append(item);
}
});
یک مهارت بنویس و «افزودن» را بزن. خرابی جلوی چشمت است: کلِ فهرست دوقلو شد — هر مهارتِ قدیمی حالا دو بار دیده میشود و با کلیکِ بعدی سه بار. چرا؟ چون append فقط اضافه میکند؛ <li> های قبلی سرِ جایشاناند و حلقه یک کپیِ کامل رویشان گذاشت.
شاید به سرت بزند کلِ کارت را خالی کنی و از نو بسازی: card.textContent = ''. امتحانش کنی، فاجعه میبینی: تیتر و فهرست و خودِ فرم همه محو میشوند — و listener فرم هم با فرم دفن میشود؛ صفحه دیگر حتی دکمهای برای افزودن ندارد.

⚠️ مواظب باش: گذاشتنِ
textContentروی یک عنصر یعنی «همهٔ بچههایش را دور بریز و فقط این متن را بگذار». فقط روی عنصری اجرایش کن که همهٔ محتوایش را خودِ حلقهات میسازد — نه روی کارتی که فرم و دکمهات هم تویش زندگی میکنند.
حالا که میدانی این چاقو کجا نباید برود، رفعِ باگ ساده است:
🔧 اگر کار نکرد: فهرست دوقلو شد؟ فقط خودِ فهرست را خالی کن، نه کارت را: قبل از حلقه بنویس
list.textContent = '';. فهرست تنها چیزی است که حلقهٔ تو میسازد، پس خالیکردنش امن است.
نسخهٔ درست، با چکِ خالینبودنِ ورودی (!== یعنی «مساوی نیست» — برعکسِ ===):
form.addEventListener('submit', function (event) {
event.preventDefault();
if (input.value !== '') {
skills.push(input.value);
input.value = '';
/* aval list ra khali kon, bad hame ra az no besaz */
list.textContent = '';
for (const skill of skills) {
const item = document.createElement('li');
item.textContent = skill;
list.append(item);
}
}
});
✅ چک کن: هر مهارتِ تازه یک بار — و فقط یک بار — به تهِ فهرست اضافه میشود، و ورودیِ خالی هیچ کاری نمیکند.
۵. forEach: همان حلقه، به سبکِ خودِ آرایه#
آرایهها راهِ دومی هم برای حلقه دارند: forEach. به آن یک function میدهی — همان جنسی که به addEventListener میدادی — و آرایه برای هر عضو یک بار صدایش میزند:
skills.forEach(function (skill) {
console.log(skill);
});
نتیجه با for...of یکی است؛ فقط سبکِ نوشتن فرق دارد. هر دو را در کدِ دیگران خواهی دید، پس هر دو را بشناس — ما در این خودآموز for...of را ادامه میدهیم چون به جملهٔ آدمیزاد شبیهتر است.
🤖 با AI: حلقهٔ رندرِ خودت را به دستیار AI ات بده و بپرس: «این کد را خطبهخط توضیح بده — و اگر وسطِ همین حلقه به
skillsعضوِ تازه push کنم چه میشود؟» جوابش را با چیزی که در آزمایشگاه میبینی چک کن؛ دستکاریِ آرایه وسطِ حلقهزدن روی همان آرایه، از آن جاهایی است که AI هم گاهی با اعتمادبهنفس اشتباه جواب میدهد.
کدِ کاملِ این فصل#
// script.js
const skills = ['HTML', 'CSS', 'flexbox', 'grid'];
const list = document.querySelector('#skills-list');
for (const skill of skills) {
const item = document.createElement('li');
item.textContent = skill;
list.append(item);
}
const form = document.querySelector('#skill-form');
const input = document.querySelector('#skill-input');
form.addEventListener('submit', function (event) {
event.preventDefault();
if (input.value !== '') {
skills.push(input.value);
input.value = '';
/* aval list ra khali kon, bad hame ra az no besaz */
list.textContent = '';
for (const skill of skills) {
const item = document.createElement('li');
item.textContent = skill;
list.append(item);
}
}
});
و index.html:
<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>مهارتهای من</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main class="card">
<h1>مهارتهای من</h1>
<ul id="skills-list"></ul>
<form id="skill-form">
<label for="skill-input">مهارت جدید:</label>
<input type="text" id="skill-input">
<button type="submit">افزودن</button>
</form>
</main>
<script src="script.js"></script>
</body>
</html>
استایلِ کارت (styles.css) در آزمایشگاه از قبل آماده است — همهاش چیزهایی که خودت در ترمهای CSS ساختهای.
واژههای تازهٔ این فصل#
| کلمه | تلفظ به حروف فارسی | یعنی چه |
|---|---|---|
| array | اَرِی | فهرستی از مقدارها در یک متغیر |
| index | ایندکس | شمارهٔ جای هر عضو؛ از صفر شروع میشود |
| push | پوش | افزودنِ یک عضو به تهِ آرایه |
for...of |
فور آو | حلقه روی تکتکِ عضوهای آرایه |
| forEach | فور ایچ | حلقهٔ خودِ آرایه که یک function میگیرد |
| createElement | کریئیت اِلِمنت | ساختنِ عنصرِ تازه که هنوز روی صفحه نیست |
| append | اَپِند | چسباندنِ عنصر به تهِ یک عنصرِ دیگر |
تمرینها
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
در فصل بعد#
دادهٔ این فصل را خودت در کد نوشتی. فصل بعد داده از خودِ اینترنت میآید: با fetch از یک سرورِ واقعی دادهٔ زنده میگیریم — و مهمتر: یاد میگیری صفحهای بسازی که وقتی شبکه قطع است هم آبرومند و سالم بماند.
به آخر این فصل رسیدی!
اگر ساختی و جواب داد، این دکمه مال توست.