آکادمی بنو/آموزش JavaScript

ES6 و جاوااسکریپت مدرن

بهنام نوبخت · ۱۴۰۵/۷/۱۱

جاوااسکریپت در طول سال‌ها امکانات بسیار زیادی پیدا کرده است. یکی از مهم‌ترین نسخه‌های جاوااسکریپت، ECMAScript 2015 یا همان ES6 است که امکانات و قابلیت‌های جدید و مهمی را به این زبان اضافه کرد.

امروزه در بسیاری از پروژه‌های جاوااسکریپت، کدهای مدرن با استفاده از قابلیت‌هایی مانند let، const، Arrow Function، Template Literal، Destructuring، Spread Operator، Rest Parameter، Default Parameter، for...of، Map و Set نوشته می‌شوند.

بعضی از این مفاهیم را در مقالات قبلی دیده‌ایم، اما در این مقاله آن‌ها را در قالب جاوااسکریپت مدرن و ES6 منظم‌تر و عمیق‌تر بررسی می‌کنیم.

در این مقاله یاد می‌گیریم:

  • ES6 چیست؟

  • ECMAScript چیست؟

  • تفاوت var، let و const

  • Template Literal

  • Default Parameters

  • Arrow Function

  • Destructuring

  • Spread Operator

  • Rest Parameter

  • Enhanced Object Literals

  • Shorthand Properties

  • Method Shorthand

  • for...of

  • Map

  • Set

  • Optional Chaining

  • Nullish Coalescing

  • و چند تکنیک مدرن دیگر

ES6 چیست؟

نام ES6 مخفف:

ECMAScript 6

است.

ECMAScript استانداردی است که جاوااسکریپت بر اساس آن توسعه پیدا می‌کند.

ES6 در سال 2015 معرفی شد و به همین دلیل با نام:

ES2015

نیز شناخته می‌شود.

قبل از ES6 نیز جاوااسکریپت وجود داشت، اما ES6 امکانات زیادی را وارد زبان کرد که باعث شدند نوشتن کدهای جاوااسکریپت راحت‌تر، خواناتر و ساختاریافته‌تر شود.

جاوااسکریپت مدرن چیست؟

وقتی درباره Modern JavaScript صحبت می‌کنیم، معمولاً منظور استفاده از قابلیت‌های جدیدتر ECMAScript و روش‌های امروزی نوشتن جاوااسکریپت است.

برای مثال کد قدیمی:

var name = "Ali";

در بسیاری از پروژه‌های جدید به شکل:

const name = "Ali";

نوشته می‌شود.

var، let و const

یکی از مهم‌ترین تغییرات ES6 معرفی:

let
const

بود.

قبل از ES6 بیشتر از var استفاده می‌شد.

var

مثال:

var name = "Ali";

console.log(name);

می‌توان مقدار آن را تغییر داد:

var name = "Ali";

name = "Reza";

console.log(name);

let

با let نیز می‌توان متغیر ساخت:

let age = 25;

age = 26;

console.log(age);

تفاوت مهم let با var در Scope و رفتار آن در Blockها است.

const

برای تعریف مقداری که قصد نداریم متغیر به مقدار دیگری اشاره کند، معمولاً از const استفاده می‌کنیم:

const country = "Türkiye";

نمی‌توانیم بعداً بنویسیم:

country = "Iran";

این کار باعث خطا می‌شود.

چه زمانی let و چه زمانی const؟

قاعده ساده:

اگر مقدار متغیر قرار است تغییر کند:

let counter = 0;

counter++;

اگر قرار نیست متغیر دوباره مقداردهی شود:

const name = "Ali";

در کد مدرن جاوااسکریپت معمولاً بهتر است ابتدا const را در نظر بگیریم و فقط وقتی نیاز به تغییر مقدار داریم از let استفاده کنیم.

Scope در let و const

let و const دارای Block Scope هستند.

مثلاً:

if (true) {

    let message = "Hello";

    console.log(message);
}

اما خارج از Block:

console.log(message);

به آن دسترسی نداریم.

Template Literal

یکی از قابلیت‌های بسیار کاربردی ES6، Template Literal است.

به جای:

const name = "Ali";

const message =
    "Hello " + name;

می‌توانیم بنویسیم:

const name = "Ali";

const message =
    `Hello ${name}`;

این روش خواناتر است.

استفاده از چند متغیر

const firstName = "Ali";
const lastName = "Ahmadi";
const age = 25;

const message =
    `${firstName} ${lastName} is ${age} years old.`;

console.log(message);

استفاده از Expression

داخل ${} می‌توانیم Expression نیز قرار دهیم:

const price = 100;
const quantity = 3;

const total =
    `Total: ${price * quantity}`;

console.log(total);

نتیجه:

Total: 300

چند خطی کردن متن

با Template Literal می‌توانیم متن چندخطی داشته باشیم:

const message = `
Hello Ali.

Welcome to
جاوااسکریپت.
`;

console.log(message);

این قابلیت برای ساخت متن‌های پویا بسیار کاربردی است.

Default Parameters

فرض کنید تابعی داریم:

function greet(name) {

    console.log(`Hello ${name}`);

}

اگر تابع را بدون مقدار اجرا کنیم:

greet();

مقدار name برابر undefined خواهد بود.

می‌توانیم مقدار پیش‌فرض تعریف کنیم:

function greet(
    name = "Guest"
) {

    console.log(`Hello ${name}`);

}

حالا:

greet();

نتیجه:

Hello Guest

اما:

greet("Ali");

نتیجه:

Hello Ali

Default Parameter برای چند مقدار

function createUser(
    name = "Unknown",
    age = 0
) {

    console.log(name);
    console.log(age);

}

مثال:

createUser();

نتیجه:

Unknown
0

Arrow Function

یکی از معروف‌ترین قابلیت‌های ES6، Arrow Function است.

تابع معمولی:

function add(a, b) {

    return a + b;

}

Arrow Function:

const add = (a, b) => {

    return a + b;

};

Arrow Function کوتاه‌تر

اگر تابع فقط یک Expression داشته باشد:

const add = (a, b) =>
    a + b;

این همان مفهوم را دارد.

مثال:

console.log(
    add(10, 20)
);

نتیجه:

30

Arrow Function با یک Parameter

اگر فقط یک Parameter داشته باشیم، می‌توانیم پرانتز را حذف کنیم:

const square = number =>
    number * number;

استفاده:

console.log(
    square(5)
);

نتیجه:

25

البته نوشتن پرانتز نیز کاملاً معتبر است:

const square = (number) =>
    number * number;

Arrow Function بدون Parameter

اگر هیچ Parameter نداشته باشیم، باید پرانتز قرار دهیم:

const sayHello = () =>
    "Hello";

Destructuring چیست؟

Destructuring یکی از قابلیت‌های مهم ES6 است که اجازه می‌دهد مقادیر Array یا Propertyهای Object را به شکل ساده‌تری داخل متغیرها قرار دهیم.

Array Destructuring

فرض کنید:

const numbers = [10, 20, 30];

روش معمول:

const first = numbers[0];
const second = numbers[1];

با Destructuring:

const [first, second] =
    numbers;

حالا:

console.log(first);
console.log(second);

نتیجه:

10
20

نادیده گرفتن مقدار در Array Destructuring

می‌توانیم بعضی مقادیر را نادیده بگیریم:

const numbers = [10, 20, 30];

const [
    first,
    ,
    third
] = numbers;

اکنون:

first = 10
third = 30

Destructuring با مقدار پیش‌فرض

const numbers = [10];

const [
    first,
    second = 20
] = numbers;

نتیجه:

first = 10
second = 20

Object Destructuring

فرض کنید:

const user = {
    name: "Ali",
    age: 25,
    city: "Istanbul"
};

روش معمول:

const name = user.name;
const age = user.age;

با Destructuring:

const {
    name,
    age
} = user;

حالا:

console.log(name);
console.log(age);

تغییر نام در Destructuring

می‌توانیم نام متغیر را تغییر دهیم:

const user = {
    name: "Ali",
    age: 25
};

const {
    name: userName,
    age: userAge
} = user;

حالا:

console.log(userName);
console.log(userAge);

مقدار پیش‌فرض در Object Destructuring

const user = {
    name: "Ali"
};

const {
    name,
    age = 18
} = user;

در اینجا:

name = "Ali"
age = 18

خواهد بود.

Destructuring در Function Parameters

یکی از کاربردهای بسیار مهم Destructuring استفاده مستقیم در Parameter تابع است.

مثلاً:

function showUser({ name, age }) {

    console.log(name);
    console.log(age);

}

سپس:

const user = {
    name: "Ali",
    age: 25
};

showUser(user);

این روش در پروژه‌های واقعی بسیار رایج است.

Spread Operator

Spread Operator با سه نقطه:

...

نوشته می‌شود.

یکی از کاربردهای آن، ترکیب یا کپی کردن Arrayها است.

مثلاً:

const first =
    [1, 2, 3];

const second =
    [4, 5, 6];

const result = [
    ...first,
    ...second
];

console.log(result);

نتیجه:

[1, 2, 3, 4, 5, 6]

کپی Array با Spread

const original = [10, 20, 30];

const copy = [...original];

اکنون copy یک Array جدید است.

مثلاً:

copy.push(40);

console.log(original);
console.log(copy);

نتیجه:

[10, 20, 30]
[10, 20, 30, 40]

Spread برای Object

Spread فقط برای Array نیست.

مثلاً:

const user = {
    name: "Ali",
    age: 25
};

const copy = {
    ...user
};

ترکیب Objectها

const user = {
    name: "Ali"
};

const details = {
    age: 25,
    city: "Istanbul"
};

const result = {
    ...user,
    ...details
};

console.log(result);

نتیجه:

{
    name: "Ali",
    age: 25,
    city: "Istanbul"
}

تغییر Property با Spread

اگر Property تکراری باشد، مقدار بعدی می‌تواند مقدار قبلی را Override کند.

مثلاً:

const user = {
    name: "Ali",
    age: 25
};

const updatedUser = {
    ...user,
    age: 26
};

حالا:

updatedUser.age = 26

است.

این روش یکی از تکنیک‌های مهم برای ایجاد نسخه جدیدی از Object بدون تغییر مستقیم Object قبلی است.

Rest Parameter

Rest Parameter نیز با:

...

نوشته می‌شود، اما کاربرد آن با Spread متفاوت است.

Rest برای جمع‌آوری چند مقدار در یک Array استفاده می‌شود.

مثال:

function sum(...numbers) {

    console.log(numbers);

}

استفاده:

sum(10, 20, 30, 40);

داخل تابع:

numbers = [10, 20, 30, 40]

است.

محاسبه مجموع با Rest

function sum(...numbers) {

    let total = 0;

    for (const number of numbers) {
        total += number;
    }

    return total;
}

استفاده:

console.log(
    sum(10, 20, 30)
);

نتیجه:

60

تفاوت Spread و Rest

اگر سه نقطه برای باز کردن یا پخش کردن مقادیر استفاده شود:

const result = [
    ...numbers
];

Spread است.

اگر برای جمع کردن چند مقدار استفاده شود:

function sum(...numbers) {
}

Rest است.

Enhanced Object Literals

ES6 روش‌های کوتاه‌تری برای ساخت Object ارائه می‌دهد.

فرض کنید:

const name = "Ali";
const age = 25;

روش قدیمی:

const user = {
    name: name,
    age: age
};

در جاوااسکریپت مدرن:

const user = {
    name,
    age
};

کافی است.

Method Shorthand

روش قدیمی:

const user = {

    sayHello: function () {
        console.log("Hello");
    }

};

روش مدرن:

const user = {

    sayHello() {
        console.log("Hello");
    }

};

این روش خواناتر است.

for...of

در مقالات قبلی با حلقه‌های جاوااسکریپت آشنا شدیم.

یکی از روش‌های مناسب برای پیمایش مقادیر قابل پیمایش، for...of است.

مثلاً:

const numbers =
    [10, 20, 30];

for (const number of numbers) {

    console.log(number);

}

نتیجه:

10
20
30

for...of با String

for...of فقط برای Array نیست.

مثلاً:

const word = "Hello";

for (const character of word) {

    console.log(character);

}

هر کاراکتر جداگانه پردازش می‌شود.

Map

Map یکی از ساختارهای داده جاوااسکریپت است که اجازه می‌دهد اطلاعات را به شکل:

Key → Value

ذخیره کنیم.

مثلاً:

const users = new Map();

اضافه کردن اطلاعات به Map

برای اضافه کردن مقدار:

users.set(
    "user1",
    "Ali"
);

users.set(
    "user2",
    "Reza"
);

دریافت مقدار از Map

console.log(
    users.get("user1")
);

نتیجه:

Ali

بررسی وجود Key

console.log(
    users.has("user1")
);

نتیجه:

true

حذف مقدار از Map

users.delete("user1");

تعداد عناصر Map

console.log(
    users.size
);

پیمایش Map

for (const [key, value] of users) {

    console.log(key);
    console.log(value);

}

اینجا از Destructuring نیز استفاده کرده‌ایم.

Set

Set ساختاری برای نگهداری مقادیر یکتا است.

مثلاً:

const numbers =
    new Set();

numbers.add(10);
numbers.add(20);
numbers.add(10);

چون 10 تکراری است، فقط یک بار ذخیره می‌شود.

مشاهده Set

console.log(numbers);

تقریباً:

Set(2) { 10, 20 }

بررسی مقدار در Set

console.log(
    numbers.has(20)
);

نتیجه:

true

حذف مقدار از Set

numbers.delete(20);

کاربرد عملی Set

فرض کنید:

const tags = [
    "جاوااسکریپت",
    "html",
    "جاوااسکریپت",
    "css",
    "html"
];

می‌توانیم تکراری‌ها را حذف کنیم:

const uniqueTags =
    [...new Set(tags)];

console.log(uniqueTags);

نتیجه:

[
    "جاوااسکریپت",
    "html",
    "css"
]

این یکی از کاربردهای بسیار رایج Set است.

Optional Chaining

Optional Chaining با:

?.

نوشته می‌شود.

فرض کنید:

const user = {
    name: "Ali"
};

اگر بخواهیم:

console.log(
    user.address.city
);

را اجرا کنیم، چون address وجود ندارد، خطا رخ می‌دهد.

با Optional Chaining:

console.log(
    user.address?.city
);

نتیجه:

undefined

و خطا رخ نمی‌دهد.

Optional Chaining در Objectهای تو در تو

مثلاً:

const user = {
    profile: {
        address: {
            city: "Istanbul"
        }
    }
};

می‌توانیم بنویسیم:

console.log(
    user.profile?.address?.city
);

Optional Chaining با Function

اگر مطمئن نیستیم یک Property شامل تابع است یا خیر:

user.sayHello?.();

در صورتی که تابع وجود داشته باشد، اجرا می‌شود.

Nullish Coalescing

عملگر:

??

زمانی کاربرد دارد که بخواهیم برای null یا undefined یک مقدار پیش‌فرض تعیین کنیم.

مثلاً:

const name = null;

const result =
    name ?? "Guest";

console.log(result);

نتیجه:

Guest

اگر مقدار موجود باشد:

const name = "Ali";

const result =
    name ?? "Guest";

نتیجه:

Ali

تفاوت ?? و ||

این دو عملگر را نباید کاملاً یکسان در نظر گرفت.

مثلاً:

const count = 0;

console.log(
    count || 10
);

نتیجه:

10

اما:

console.log(
    count ?? 10
);

نتیجه:

0

چون ?? فقط زمانی سراغ مقدار پیش‌فرض می‌رود که مقدار null یا undefined باشد.

ترکیب قابلیت‌های جاوااسکریپت مدرن

قدرت واقعی این امکانات زمانی مشخص می‌شود که آن‌ها را با هم ترکیب کنیم.

فرض کنید:

const user = {
    name: "Ali",
    age: 25,
    address: {
        city: "Istanbul"
    }
};

می‌توانیم:

const {
    name,
    age,
    address
} = user;

const city =
    address?.city ?? "Unknown";

const message =
    `${name} is ${age} years old and lives in ${city}.`;

console.log(message);

این مثال ترکیبی از:

Destructuring
Optional Chaining
Nullish Coalescing
Template Literal
const

است.

مثال عملی: ساخت Product

فرض کنید اطلاعات محصول:

const product = {
    name: "Laptop",
    price: 1200,
    discount: 100
};

با Destructuring:

const {
    name,
    price,
    discount = 0
} = product;

قیمت نهایی:

const finalPrice =
    price - discount;

و نمایش:

const message =
    `${name} - Final Price: ${finalPrice}`;

console.log(message);

مثال عملی: به‌روزرسانی Object

فرض کنید:

const user = {
    name: "Ali",
    age: 25,
    city: "Istanbul"
};

می‌خواهیم سن را تغییر دهیم، بدون اینکه Object اصلی را تغییر دهیم:

const updatedUser = {
    ...user,
    age: 26
};

حالا:

console.log(user.age);
console.log(updatedUser.age);

نتیجه:

25
26

مثال عملی: Function با Rest

function calculateAverage(...numbers) {

    if (numbers.length === 0) {
        return 0;
    }

    let total = 0;

    for (const number of numbers) {
        total += number;
    }

    return total / numbers.length;
}

استفاده:

console.log(
    calculateAverage(
        10,
        20,
        30
    )
);

نتیجه:

20

مثال عملی: ترکیب Arrayها

فرض کنید:

const frontend = [
    "HTML",
    "CSS"
];

const backend = [
    "C#",
    "SQL"
];

ترکیب:

const skills = [
    ...frontend,
    ...backend
];

نتیجه:

[
    "HTML",
    "CSS",
    "C#",
    "SQL"
]

جاوااسکریپت مدرن و خوانایی کد

هدف ES6 فقط کوتاه‌تر کردن کد نیست.

یکی از اهداف مهم این قابلیت‌ها، خوانایی و ساختار بهتر کد است.

مثلاً:

const userName = user.name;
const userAge = user.age;

می‌تواند به شکل:

const {
    name: userName,
    age: userAge
} = user;

نوشته شود.

البته نباید صرفاً برای کوتاه کردن کد از Destructuring یا سایر قابلیت‌های جدید استفاده کنیم. مهم‌تر از کوتاه بودن کد، قابل فهم بودن آن است.

اشتباهات رایج

اشتباه اول: تغییر مقدار const

این کد اشتباه است:

const name = "Ali";

name = "Reza";

اگر نیاز به تغییر دارید، از let استفاده کنید.

اشتباه دوم: اشتباه گرفتن Spread و Rest

این دو از یک علامت استفاده می‌کنند:

...

اما کاربردشان متفاوت است.

Spread مقادیر را باز می‌کند.

Rest مقادیر را جمع می‌کند.

اشتباه سوم: تصور اینکه Spread یک Deep Copy است

مثلاً:

const copy = {
    ...user
};

یک کپی سطحی یا Shallow Copy ایجاد می‌کند.

اگر Object دارای Objectهای داخلی باشد، داستان پیچیده‌تر می‌شود و نباید تصور کنیم تمام سطوح به صورت مستقل کپی شده‌اند.

اشتباه چهارم: استفاده نادرست از Optional Chaining

Optional Chaining برای جلوگیری از برخی خطاهای دسترسی به مقادیر null یا undefined مفید است، اما نباید بدون دلیل همه Propertyها را با ?. بنویسیم.

اشتباه پنجم: استفاده نادرست از ??

اگر مقدار 0 یا false باید معتبر باقی بماند، ?? می‌تواند انتخاب مناسبی نسبت به || باشد.

جدول قابلیت‌های مهم ES6 و جاوااسکریپت مدرن

قابلیتکاربرد

let

متغیر قابل تغییر

const

متغیر با Binding غیرقابل انتساب مجدد

Template Literal

ساخت Stringهای پویا

Default Parameter

مقدار پیش‌فرض Parameter

Arrow Function

Syntax کوتاه‌تر برای Function

Destructuring

استخراج مقدار از Array/Object

Spread

باز کردن مقادیر

Rest

جمع کردن مقادیر

Object Shorthand

ساخت کوتاه‌تر Object

for...of

پیمایش مقادیر

Map

ذخیره Key/Value

Set

ذخیره مقادیر یکتا

Optional Chaining

دسترسی امن‌تر به Propertyهای احتمالی

Nullish Coalescing

مقدار پیش‌فرض برای null و undefined

تمرین‌ها

تمرین ۱

یک متغیر با const ایجاد کنید که نام شما را نگه دارد.

سپس یک متغیر let برای سن ایجاد کنید و مقدار آن را تغییر دهید.

تمرین ۲

با Template Literal جمله زیر را ایجاد کنید:

My name is Ali and I am 25 years old.

نام و سن باید از متغیر دریافت شوند.

تمرین ۳

تابعی ایجاد کنید که اگر نامی دریافت نکرد، مقدار Guest را استفاده کند.

تمرین ۴

یک Array شامل پنج عدد ایجاد کنید و با Destructuring سه مقدار اول را داخل سه متغیر قرار دهید.

تمرین ۵

دو Array بسازید و با Spread آن‌ها را ترکیب کنید.

تمرین ۶

تابعی با Rest Parameter ایجاد کنید که هر تعداد عدد دریافت کرده و مجموع آن‌ها را برگرداند.

تمرین ۷

یک Object کاربر ایجاد کنید و با Object Destructuring نام و سن را استخراج کنید.

تمرین ۸

یک Array دارای مقادیر تکراری ایجاد کنید و با Set مقادیر تکراری را حذف کنید.

تمرین ۹

یک Object تو در تو ایجاد کنید و با Optional Chaining به یک Property داخلی دسترسی پیدا کنید.

تمرین ۱۰

با ?? برای مقدار null یک مقدار پیش‌فرض تعیین کنید.

چالش عملی

یک برنامه کوچک برای مدیریت اطلاعات یک کاربر ایجاد کنید.

اطلاعات اولیه:

const user = {
    firstName: "Ali",
    lastName: "Ahmadi",
    age: 25,
    skills: [
        "HTML",
        "CSS",
        "جاوااسکریپت"
    ],
    address: {
        city: "Istanbul"
    }
};

برنامه باید:

  1. با Destructuring نام و نام خانوادگی را دریافت کند.

  2. با Template Literal یک پیام معرفی بسازد.

  3. با Optional Chaining شهر را دریافت کند.

  4. اگر شهر وجود نداشت، با ?? مقدار Unknown قرار دهد.

  5. یک Skill جدید با Spread به Array اضافه کند.

  6. با Set یک لیست Skill بدون تکرار ایجاد کند.

  7. یک تابع با Rest Parameter بسازید که تعداد Skillها را محاسبه کند.

  8. یک Object جدید با Spread ایجاد کنید که سن کاربر در آن تغییر کرده باشد.

  9. در صورت نیاز از Arrow Function استفاده کنید.

هدف این تمرین این است که چند قابلیت جاوااسکریپت مدرن را در یک پروژه کوچک با هم استفاده کنید.

جمع‌بندی

در این مقاله با بخش مهمی از ES6 و جاوااسکریپت مدرن آشنا شدیم.

یاد گرفتیم:

  • ES6 یا ES2015 چیست.

  • ECMAScript چه ارتباطی با جاوااسکریپت دارد.

  • چگونه از let و const استفاده کنیم.

  • Template Literal چگونه کار می‌کند.

  • Default Parameter چیست.

  • Arrow Function چگونه نوشته می‌شود.

  • Array و Object Destructuring چیست.

  • Spread Operator چگونه کار می‌کند.

  • Rest Parameter چه کاربردی دارد.

  • چگونه Objectها را به شکل کوتاه‌تر ایجاد کنیم.

  • for...of چگونه استفاده می‌شود.

  • Map چیست.

  • Set چیست.

  • چگونه مقادیر تکراری را با Set حذف کنیم.

  • Optional Chaining چیست.

  • Nullish Coalescing چه کاربردی دارد.

  • چگونه چند قابلیت مدرن جاوااسکریپت را با یکدیگر ترکیب کنیم.

در این مرحله شما بخش بزرگی از Syntaxهای پرکاربرد جاوااسکریپت را می‌شناسید و می‌توانید کدهای مدرن‌تر و خواناتری بنویسید.

۰۰

نظرات

کد در دسترس نیست

هنوز نظری ثبت نشده است.