جاوا اسکریپت ES6 چیست؟
![جاوا اسکریپت ES6 چیست؟](https://sabzlearn.ir/wp-content/uploads/2024/01/JavaScript-ES6-1.webp)
جاوا اسکریپت ES6 چیست؟ ES6 در جاوا اسکریپت یا همان ECMAScript 2015، ششمین نسخه از زبان برنامهنویسی ECMAScript است. این نسخه از زبان برنامهنویسی جاوا اسکریپت در سال 2015 معرفی شد و اساساً مجموعه قوانینی است که این زبان را تعریف میکند. در اصل ECMAScript استاندارد است و جاوا اسکریپت زبانی بهحساب میآید که از این استاندارد پیروی میکند. در سال 2015، جاوا اسکریپت ویژگیهای مشخصشده در ECMAScript 2015 را در خود جای داد و امروزه هر دو اصطلاح اغلب بهجای یکدیگر استفاده میشوند.
در مطلب پیشِرو از مجله سبزلرن این بار قصد داریم به این پرسش که جاوا اسکریپت ES6 چیست، تاریخچه آن به کجا و کی بازمیگردد و ویژگی آن چه هستند، پاسخی کامل و جامع ارائه کنیم. پس با ما همراه باشید.
اکما اسکریپت و جاوا اسکریپت
اکما اسکریپت 6، همانطور که در ECMA-262 تعریف شده است، به عنوان طرحی برای توسعه نوعی زبان برنامهنویسی همهکاره عمل میکند. در اصل این طرح، دستورالعملهای استانداردشدهای برای ایجاد چنین زبانی ارائه میدهد که توسط ECMA International معرفی شده است و به عنوان مدلی عمل میکند که به ما میآموزد چگونه یک زبان برنامهنویسی ایجاد کنیم.
از طرف دیگر زبان برنامه نویسی جاوا اسکریپت یک پیادهسازی عملی از مشخصات ECMAScript است. در اصل جاوا اسکریپت نوعی زبان برنامهنویسی همهمنظوره محسوب میشود که به استانداردهای مشخصشده در ECMAScript پایبند است. اساساً، اکما اسکریپت برنامهای بهحساب میآید که نحوه استفاده از یک زبان برنامهنویسی را در عمل نشان میدهد.
جاوا اسکریپت ES6 چیست؟
سؤال اصلی اینجاست، جاوا اسکریپت ES6 چیست و چه تفاوتی با جاوا اسکریپت معمولی دارد؟ ES6 یا ECMAScript 2015 چندین سال است مورد استفاده قرار میگیرد و به توسعهدهندگان این امکان را میدهد که کدهای خود را به شیوهای خواناتر از جاوا اسکریپت معمولی بنویسند. میتوان آن را بهطور دقیق به عنوان ابزاری توصیف کرد که ما را قادر میسازد با نوشتن کد کمتر و در عین حال دستیابی به عملکرد بیشتر، کارآمدتر باشیم و این ویژگیها امکان یادگیری جاوا اسکریپت را برای ما ساده خواهد کرد.
ES6 چندین ویژگی مهم، از جمله const و let برای اعلانهای متغیر، توابع پیکان برای عبارات مختصر تابع، الفاظ الگو برای مدیریت رشتههای رساتر، پارامترهای پیشفرض برای آرگومانهای تابع و پیشرفتهای مختلف دیگر را به ارمغان آورد که در ادامه به معرفی آنها خواهیم پرداخت.
تاریخچه ES6
مشخصات ECMAScript، زبان اسکریپت استانداردشده، توسط Brendan Eich، خالق زبان برنامهنویسی جاوا اسکریپت، زمانی که در نت اسکیپ بود، توسعه داده شد. نت اسکیپ که به خاطر توسعه مرورگرهای وب خود شناخته میشود، ابتدا ECMAScript را با نام Mocha و سپس LiveScript نامید و در نهایت روی جاوا اسکریپت مستقر شد. این زبان توسط Sun Microsystems و Netscape در دسامبر 1995 اعلام شد.
در نوامبر 1996، نت اسکیپ برای افزایش استانداردسازی جاوا اسکریپت خواستار جلسهای با ECMA International شد. مجمع عمومی ECMA اولین نسخه ECMA-262 را در ژوئن 1997 به تصویب رساند. نام ECMAScript از مذاکرات بین سازمانها، از جمله Netscape و مایکروسافت حاصل شد. هدف جاوا اسکریپت و جی اسکریپت سازگاری با ECMAScript است و ویژگیهای اضافی فراتر از مشخصات ECMA را ارائه میدهد. قبل از پرداختن به ES6، درک اولیه جاوا اسکریپت توصیه میشود.
مهمترین ویژگیهای جاوا اسکریپت ES6 چیست؟
جاوا اسکریپت ES6 تغییرات قابلتوجهی را در زبان جاوا اسکریپت ارائه میکند که شامل طیف وسیعی از ویژگیهای جدید مانند کلیدواژههای let و const، توابع پیکان، پارامترهای پیشفرض، الفاظ الگو، تخصیص تخریب ساختار، وعدهها، کلاسها و غیره میشود. هدف این پیشرفتها سادهسازی و ارتقای تجربه برنامهنویسی جاوا اسکریپت است که آن را لذتبخشتر و کارآمدتر میکند. در این بخش، برخی از بهترین و پرکاربردترین ویژگیهای ES6 را بررسی خواهیم کرد که میتوانند به طور قابلتوجهی شیوههای کدنویسی جاوا اسکریپت روزانه ما را بهبود بخشند.
Const در ES6
کلمه کلیدی const برای تعریف متغیرهای ثابتی که مقادیر آنها تغییرناپذیر باقی میماند استفاده میشود. این متغیرها غیرقابل تغییر هستند، مگر زمانی که برای اشیاء اعمال شوند. به عنوان مثال، کد زیر را برای نشان دادن استفاده از کلمه کلیدی const در سناریوهای مختلف در نظر بگیرید:
// Const const name = 'Mukul'; console.log(name); // This will display 'Mukul' in the console. // Attempting to reassign a const variable name = 'Rahul'; console.log(name); // This will result in a TypeError. // Trying to declare a const variable first // and then initialize it in another line const org_name; org_name = "Sabzlearn"; console.log(org_name); // This will throw a syntax error: missing initializer in const declaration.
در مثال بالا، به متغیر ثابت name مقدار Mukul اختصاص داده شده است و هر گونه تلاش برای تخصیص مجدد آن و همچنین تلاش برای اعلام نوعت متغیر ثابت بدون مقداردهی اولیه بلافاصله، منجر به خطا میشود.
کلمه کلیدی let در جاوا اسکریپت ES6
کلمه کلیدی let در جاوا اسکریپت ES6 برای ایجاد متغیرهای قابل تغییر به کار میرود و امکان تغییر مقادیر آنها را فراهم میکند. این کلمه مشابه کلمه کلیدی var عمل میکند اما تمایزات قابلتوجهی با آن بهویژه از نظر محدوده دارد که این تمایز در مقایسه با var آن را به انتخابی ارجح تبدیل میکند. برای نمونه، مثال زیر را در نظر بگیرید که استفاده از کلمه کلیدی let را نشان میدهد:
// let let name = 'Mukul'; console.log(name); // Outputs Mukul name = 'Rahul'; console.log(name); // Outputs Rahul // Attempting to declare a let variable first and then initialize it on another line let org_name; org_name = "Sabzlearn"; console.log(org_name); // Outputs sabzlearn
در مثال بالا، متغیر let name در ابتدا به مقدار Mukul اختصاص یافته و بعداً به Rahul تغییر یافته است. علاوه بر این، متغیر org_name ابتدا اعلام و سپس با sabzlearn در خط بعدی مقداردهی اولیه میشود.
توابع پیکان در جاوا اسکریپت ای اس ٦
توابع پیکان (Arrow functions)، سینتکس و نحو مختصرتری را برای بیان توابع، افزایش خوانایی کد و اتخاذ رویکردی مدرن ارائه میکنند. به عنوان مثال، قطعه کد زیر را در نظر بگیرید که ایجاد و اجرای توابع پیکان را نشان میدهد:
// Function declaration using the function keyword function simpleFunc(){ console.log("Declared using the function keyword"); } simpleFunc(); // Function declared using arrow functions const arrowFunc = () => { console.log("Declared using arrow functions"); } arrowFunc();
در مثال بالا، تابع اول، simpleFunc با استفاده از کلمه کلیدی معمولی function اعلام شده، در حالی که تابع دوم، arrowFunc با استفاده از توابع پیکان اعلان شده است. هر دو تابع خروجی یکسانی دارند که مثال بالا تطبیقپذیری و مختصر بودن توابع پیکان را نشان میدهند.
الفاظ الگو
الفاظ یا الفبای الگو (Template literal) راهی راحت برای ترکیب متغیرهای جاوا اسکریپت در رشتهها بدون نیاز به عملگر + ارائه میدهند. این الفاظ با استفاده از بکتیکهای دوتایی (”) تعریف میشوند. مثال زیر نحوه استفاده از این الفاظ را بیان میکند:
// Without Template Literal var name = 'Sabzlearn'; console.log('Printed without using Template Literal'); console.log('My name is ' + name); // With Template Literal const name1 = 'Sabzlearn'; console.log('Printed by using Template Literal'); console.log(`My name is ${name1}`);
در این مثال، اولین مجموعه از عبارات log برای الحاق رشتهها استفاده میکند، در حالی که مجموعه دوم از الفاظ الگو بهره میبرد. هر دو رویکرد خروجی یکسانی دارند و نشان میدهند که چگونه الفاظ الگو درونیابی رشتهای را به شیوهای مختصر و خوانا سادهتر میکنند.
تخریب ساختار شی و آرایه
تخریب ساختار در جاوا اسکریپت ES6 شامل تجزیه ساختارهای پیچیده (مانند اشیاء یا آرایهها) به اجزای سادهتر است. از طریق تخصیص ساختار، ما میتوانیم به طور مؤثری اشیا و آرایه را در متغیرهای مجزا باز کنیم که کد زیر نحوه استفاده از این ویژگی را بیان میکند:
// Object Destructuring const college = { name: 'DTU', est: '1941', isPvt: false }; let {name, est, isPvt} = college; console.log(name, est, isPvt); // Array Destructuring const arr = ['lionel', 'messi', 'barcelona']; let [value1, value2, value3] = arr; console.log(value1, value2, value3);
در مثال بالا، ساختارشکنی شی به شیء college اعمال میشود و ویژگیهای آن را به متغیرهای جداگانه استخراج میکند، در حالی که ساختارشکنی آرایه در آرایه arr برای تخصیص مقادیر آن به متغیرهای جداگانه استفاده میشود. خروجی مقادیر استخراجشده سادگی و اثربخشی تخریب ساختار در مدیریت ساختارهای داده پیچیده را نشان میدهد.
پارامترهای پیشفرض
در جاوا اسکریپت ES6، امکان تعریف پارامترهای پیشفرض در تابعی خاص وجود دارد و در صورتی که پارامتری بهصراحت ارائه نشده باشد، مقدار پیشفرض برای آن ارائه میشود. به عنوان مثال، کدهای زیر را در نظر بگیرید که استفاده از پارامترهای پیشفرض را در یک تابع نشان میدهد:
function sum(a, b = 1){ return a + b; } console.log(sum(5, 2)); console.log(sum(3));
در مثال فوق، تابع sum دو پارامتر a و b را میگیرد که به b مقدار پیشفرض 1 اختصاص داده شده است. هنگام فراخوانی تابع، اگر b ارائه نشده باشد، به طور پیشفرض 1 است.
کلاسهای جاوا اسکریپت ES6
در جاوا اسکریپت ES6، مفهوم کلاسها به این زبان برنامهنویسی معرفی شد که امکان ایجاد اشیاء جدید را از طریق استفاده از مفهومی به نام سازنده فراهم میکرد. هر کلاس مجاز است فقط یک سازنده داشته باشد. مثال زیر نحوه تعریف کلاسها را در ES6 نشان میدهد:
// Classes in ES6 class Vehicle{ constructor(name, engine){ this.name = name; this.engine = engine; } } const bike1 = new Vehicle('Ninja ZX-10R', '998cc'); const bike2 = new Vehicle('Duke', '390cc'); console.log(bike1.name); // Outputs Ninja ZX-10R console.log(bike2.name); // Outputs Duke
در مثال بالا، کلاس Vehicle سازندهای دارد که ویژگیهایی مانند name و engine را مقداردهی اولیه میکند. پس از آن، دو نمونه از کلاس، bike1 و bike2 با مقادیر خاص ایجاد میشوند.
پارامتر Rest و عملگر Spread در ES6
پارامتر Rest در ES6 برای نمایش تعداد متغیری از پارامترها به عنوان نوعی آرایه استفاده میشود و به آنها اجازه میدهد به طور جمعی به تابعی خاص منتقل شوند. توجه به مثال زیر برای درک این مفهوم مهم است:
// ES6 rest parameter function calculateSum(...input){ let sum = 0; for(let i of input){ sum += i; } return sum; } console.log(calculateSum(1,2)); // Outputs 3 console.log(calculateSum(1,2,3)); // Outputs 6 console.log(calculateSum(1,2,3,4,5)); // Outputs 15
در مثال فوق، تابع «calculateSum» تعداد متغیری از پارامترها را با استفاده از پارامتر Rest میگیرد و خروجی مجموع محاسبهشده برای ترکیبهای ورودی مختلف را نشان میدهد.
از طرفی دیگر عملگر spread در جاوا اسکریپت تبدیل یک آرایه با n عناصر را به لیستی از عناصر متمایز n تایی ساده میکند. مثال زیر اجرای عملی عملگر spread را نشان میدهد:
// Spread operator let numbers = [1, 2, 3, -1]; console.log(...numbers); console.log(Math.max(...numbers)); // Outputs -1
در این مثال، عملگر spread برای گسترش آرایه numbers به عناصر جداگانه هنگام ثبت آنها و یافتن حداکثر مقدار با استفاده از «Math.max» استفاده میشود.
حلقه for/of
حلقه for/of سینتکسی مختصر برای پیمایش آیتمهای تکرارپذیر فراهم میکند و جایگزین کوتاهتری برای سایر ساختارهای حلقه ارائه خواهد کرد. مثال زیر نحوه استفاده از این حلقه جاوا اسکریپت را بیان میکند.
const myArray = [5, 55, 33, 9, 6]; for(let element of myArray){ console.log(element); }
در قطعه کد بالا، حلقه for/of روی هر عنصر آرایه «myArray» پیمایش انجام داده و خروجی هر عنصر را جداگانه نمایش میدهد. حلقه for/of بهویژه برای ساده کردن فرآیند پیمایش هنگام برخورد با اشیاء تکرارپذیر مفید است.
نقشهها و مجموعهها در ES6
نقشه یا Map در جاوا اسکریپت ES6 به عنوان نوعی ساختار داده برای ذخیره آیتمهای متعدد به شکل جفتهای کلید-مقدار عمل میکنند، جایی که کلیدها میتوانند از هر نوع دادهای باشند. از سوی دیگر، مجموعهها دادههایی هستند که فقط مقادیر منحصربهفرد را ذخیره کرده و اجازه میدهند هر مقدار فقط یک بار ذخیره شود. مجموعهها میتوانند مقادیر هر نوع دادهای را در خود جای دهند.
برای درک عملی این موضوع، مثال زیر را در نظر بگیرید که استفاده از Map و Set را نشان میدهد:
// Maps in JavaScript const myMap = new Map([ ["stringKey", 23], [48, "numberedKey"] ]); myMap.set(false, 0); myMap.set(1, true); console.log( myMap.get("stringKey"), myMap.get(48), myMap.get(false), myMap.get(1) ); // Sets in JavaScript const mySet = new Set(["string value", "string value"]); mySet.add(24); mySet.add(24); mySet.add(3); console.log(mySet);
در این مثال، نقشه جاوا اسکریپت «myMap» شامل جفتهای کلید-مقدار مختلف است و مجموعه جاوا اسکریپت «mySet» تضمین میکند که فقط مقادیر منحصربهفرد ذخیره میشوند. خروجی مثال فوق، بازیابی مقادیر از Map و محتوای Set را منعکس میکند و کاربرد عملی Maps و Sets را در جاوا اسکریپت نشان میدهد.
وعدهها در جاوا اسکریپت
وعدهها(Promises) در جاوا اسکریپت برای رسیدگی به وظایف ناهمزمان استفاده میشوند که ممکن است اجرای آن مدتی طول بکشد. آنها راهی برای ادغام یکپارچه کدهای همزمان و ناهمزمان ارائه میدهند. مثال زیر نحوه ایجاد و پیادهسازی وعده در جاوا اسکریپت را نشان میدهد:
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { resolve("Promise is Working"); }, 2000); }); myPromise.then((value) => { console.log(value); });
در مثال فوق، وعده با نام myPromise ایجاد و در اجرای آن، پاسخ تأخیری Promise is Working ارسال یا به اصطلاح حل میشود. سپس از متد then برای رسیدگی به حل موفقیتآمیز وعده استفاده میشود و خروجی «Promise is Working» را چاپ میکند. مثال فوق این نشاندهنده کاربرد وعدهها در مدیریت عملیات ناهمزمان در جاوا اسکریپت است.
سیمبل در جاوا اسکریپت
Symbol نوعی داده ابتدایی محسوب میشود که در جاوا اسکریپت ES6 معرفی شده است و به عنوان راهی برای تعیین شناسههای پنهانی عمل میکند که مستقیماً توسط کدهای دیگر قابل دسترسی نیستند. برای درک عملی، مثال کد زیر را در نظر بگیرید که استفاده از نوع داده Symbol را نشان میدهد:
const company = { name: "Sabzlearn", description: "A Computer Science portal for all user." } let shortNameSymbol = Symbol("short_name"); company[shortNameSymbol] = "Sl"; console.log(`${company.name}, \n${company.description}`); console.log(`Company's Short Name using company.short_name: ${company.short_name} `); console.log(`Company's Short Name using company[short_name]: ${company[shortNameSymbol]} `);
در مثال بالا، سیمبل یا نمادی به نام «shortNameSymbol» به عنوان یک شناسه پنهان برای ذخیره نام کوتاه company استفاده میشود. خروجی دسترسی به ویژگیهای company را ارائه داده و منحصربهفرد بودن و حریم خصوصی سیمبلهای جاوا اسکریپت را در مقایسه با نوع دادههایی معمولی نشان میدهد.
متدهای رشته در جاوا اسکریپت ES6
جاوا اسکریپت سه متد رشته معرفی شده در ES6 را برای دستکاری رشتههای پیشرفته ارائه میدهد:
- startsWith: این متد فقط در صورتی true را برمیگرداند که رشته آزمایشی با رشته مشخصشده شروع شود.
- endsWith: اگر رشته با مقدار رشته ارائهشده به پایان برسد، مقدار true را برمیگرداند.
- Includes: اگر رشته آزمایشی حاوی مقدار مشخصشده باشد، متد include مقدار true را برمیگرداند.
مثال زیر نحوه استفاده از متدهای رشته را نشان میدهد:
// String startsWith() const textStart = "This string implements the startsWith() method."; console.log( textStart.startsWith("This string"), textStart.startsWith("This is") ); // String endsWith() const textEnd = "This string implements the endsWith() method."; console.log( textEnd.endsWith("clear() method."), textEnd.endsWith("method.") ); // String includes() const textIncludes = "This string implements the includes() method."; console.log( textIncludes.includes("includes()"), textIncludes.includes("My name") );
در مثال بالا، سه متد رشته startsWith، endsWith و include برای رشتههای مختلف اعمال میشوند و خروجی نشان میدهد که آیا شرایط مشخصشده برآورده شده است یا خیر. این مثال به ما نشان میدهد که چگونه میتوان از این متدها برای کارهای مختلف دستکاری رشته در جاوا اسکریپت استفاده کرد.
متدهای آرایه در جاوا اسکریپت
جاوا اسکریپت چندین متد آرایه را در ES6 معرفی میکند که دستکاری آرایه را افزایش میدهند که فهرست آنها به صورت زیر است:
- from: این متد نوعی آرایه از هر شیء تکرارپذیری که دارای ویژگی length مرتبط است تولید میکند.
- keys: آرایهای حاوی کلیدهای تکرارکننده آرایه را برمیگرداند.
- find: متد find مقدار اولین عنصر آرایه را برمیگرداند که شرایط مشخصشده توسط تابع ارسالشده را برآورده میکند.
- findIndex: این متد ایندکس یا همان اندیس اولین عنصر آرایه را برمیگرداند که با شرایط تعریف شده توسط تابع ارسالشده مطابقت دارد.
مثال زیر در این رابطه مهم است:
// Array.from() method const newStringArray = Array.from("Sabzlearn"); console.log("Using Array.from(): ", newStringArray); // Array.keys() method const dairyProducts = ["Curd", "Cheese", "Butter", "Ice-Cream"]; const arrayKeysIterator = dairyProducts.keys(); console.log("Using Array.keys(): "); for(let key of arrayKeysIterator){ console.log(key); } // Array.find() method const wordArray = ["clock", "strong", "planet", "earth"]; const lessThanSix = (item) => { return item.trim().length < 6; } console.log("Using Array.find(): ", wordArray.find(lessThanSix)); console.log("Using Array.findIndex(): ", wordArray.findIndex(lessThanSix));
در مثال بالا متدهای آرایه Array.from، Array.keys، Array.find و Array.findIndex برای سناریوهای مختلف اعمال میشوند و کاربرد عملی خود را در کارهای دستکاری آرایه در جاوا اسکریپت نشان میدهند.
متد Object.entries در جاوا اسکریپت ES6
متد Object.entries برای تبدیل نوعی آرایه تک ارزشی به شی آرایه استفاده میشود، جایی که هر آیتم نشاندهنده یک جفت کلید-مقدار است. مثال زیر پیادهسازی متد Object.entries را نشان میدهد:
const myArr = ["Sabzlearn", "A Computer Science Portal for all users"]; const arr = myArr.entries() for(let item of arr){ console.log(item); }
در مثال بالا، متد Object.entries روی آرایه myArray اعمال میشود که در نتیجه یک شی آرایه با جفتهای کلید-مقدار ایجاد میشود. خروجی هر ورودی را به صورت یک آرایه نمایش میدهد که عنصر اول کلید و عنصر دوم مقدار مربوطه است.
جمع بندی
جاوا اسکریپت از بدو تولد تا به حال دچار تغییرات گوناگونی شده است که از مهمترین این تغییران میتوان به استانداردسازی آن که به نام ECMAScript 2015 یا جاوا اسکریپت ES6 شناخته میشود، اشاره کرد. ES6 ویژگیهای ارزشمندی مانند کلاسها، ماژولها، توابع پیکان، تخریب ساختار و غیره را معرفی میکند که این ویژگیها به تجربه سادهتر و کاربرپسندتر هنگام کار با جاوا اسکریپت کمک میکنند. در مطلب فوق از مجله سبزلرن اطلاعات نسبتاً کامل و مطلوبی در رابطه با جاوا اسکریپت ES6 و ویژگیهای آن ارائهشده که میتواند برای کاربران مفید واقع شود.
چگونه میتوانم در جاوا اسکریپت حرفه ای تر شویم؟
با خواندن مقالات مختلف احتمالا بتوانید تا حدی به بخشهای مختلف جاوا اسکریپت مسلط شوید اما قطعا بیبرنامه بودن و اصولی نبودن مسیر یادگیری باعث میشود شما نسبت به زبان برنامه نویسی جاوا اسکریپت دلسرد شوید یا اینکه آن را بصورت کامل یاد نگیرید؛ اما نگران این موضوع نباشید، تیم سبزلرن برای شما دوره آموزش صفر تا صد جاوا اسکریپت را بهصورت کاملا رایگان قرار داده تا بتوانید بهصورت اصولی و حرفهای در زبان جاوا اسکریپت متخصص شوید. اما این همه ماجرا نیست!! این دوره علاوه بر رایگان بودن آن، دارای پشتیبانی انلاین نیز هست و هرکجا به هر مشکلی برخوردید، افراد متخصص در این زبان آماده پاسخگویی به اشکالات و سوالات شما هستند، چی بهتر از این؟ پس فرصت را غنیمت بشمرید و همین الان در این دوره شرکت کنید و بصورت تخصصی یادگیری خودتان را شروع کنید.
پیشنهاد مطالعه
![بهترین ترکیب رنگ برای طراحی سایت چیست؟](https://sabzlearn.ir/wp-content/uploads/2024/08/shakhes-2.webp)
![DevOps چیست؟](https://sabzlearn.ir/wp-content/uploads/2024/07/shakhes-1.webp)
خیلی عالی
البته قبل این مقاله داخل دوره js استاد سعیدی راد سطح پیشرفته جلسه تاریخچه جاوا اسکریپت کاملا با این ES6
و کلا اکما اسکریپت آشنا شده بودم ولی بازم خوندن این مطلب خالی از لطف نبود
مرسی از تیم سبز لرن و استاد سعیدی راد و نویسنده این مقاله
🙏❤️
خوب بود
❤️❤️