هر توسعهدهنده جاوااسکریپت باید مفاهیم اساسی این زبان برنامه نویسی را درک کند. در این مقاله ۱۱ مفهوم مهم در جاوااسکریپت که لازم است بدانید، به اختصار بررسی میکنیم.
مخفف Immediately Invoked Function Expression است. تابعی است که بلافاصله بعد از ساختهشدن، فراخوانی میشود.
نحوه تعریف یک IIFE را با مثال زیر نشان دادهایم:
(() => console.log(‘Hello world’))();
در این مثال، به محض اجرای کد، در کنسول عبارت Hello world چاپ میشود. یکی از دلایل استفاده از IIFE محافظت از دسترسی به متغیرها است. متغیرهایی که در IIFE تعریف شوند خارج از این تابع قابل دسترسی نیستند. این روش کدنویسی نگهداری کد را آسانتر میکند و از بههم ریختن کد جلوگیری میکند.
[button class=”github-btn” href=”http://frontcast.ir/javascript-function-execution”]ویدیوی آموزشی: اجرای توابع در جاوااسکریپت[/button]
این ساختار علاوه بر جاوااسکریپت در اغلب زبانهای برنامهنویسی استفاده میشود. یک ایده محبوب است تا بتوانیم کد خود را در لایههای مختلف به صورت مجزا از هم مثل داده، ظاهر برنامه (view) و منطق (logic) سازماندهی کنیم.
در پروژههای بزرگ، به یک ساختار برای مقیاسبندی نیاز داریم. MVC یکی از بهترین ساختارها برای پروژههای بلندمدت است. در آینده هنگام افزودن ویژگیهای جدید به پروژه یا بررسی اشکالات آن، از خودتان برای وقتی که در ابتدای کار برای پیادهسازی ساختار MVC صرف کردهاید، تشکر خواهیدکرد.
[button class=”github-btn” href=”http://frontcast.ir/course/mern-stack”]دوره جامع MERN Stack[/button]
از این مفهوم زمانی استفاده میکنیم که با یک تابع داخلی سروکار داریم. این تابع همیشه به متغیرها و پارامترهای تابع خارجی آن، حتی زمانی که تابع خارجی عملیات return را انجام داده است، دسترسی دارد .
Closure امکان دسترسی به دادههای داخل یک تابع را بدون این که مستقیما تغییری در آنها ایجاد کنیم، فراهم میکند. در چنین حالتی میتوانیم از کدهای خود درحالی که به دیگران امکان توسعه کد خود را دادهایم، محافظت کنیم. به خصوص زمانی که کتابخانه (library) عمومی ارائه میدهیم.
const sayHelloTo = name => { let message = ‘Hello ‘ + name; return () => console.log(message); } const sayHelloToAmy = sayHelloTo(‘Amy’); sayHelloToAmy(); // Hello Amy
Async/await امکان پردازش Asynchronous یا ناهمگام را برای شما فراهم میکند. معمولا هنگام فراخوانی API، با پردازش ناهمگام رو به رو میشوید زیرا دادهها باید قبل از نمایش، کاملا دریافت (fetch) شوند. با استفاده از این مفاهیم دیگر نیازی به نوشتن کدهای تو در تو وجود ندارد.
در ادامه مثالی از استفاده از async/await را مشاهده میکنید:
const displayData = async () => { const data = await fetch(‘https://api.github.com/repositories'); const jsonData = await data.json(); console.log(jsonData); }; displayData();
[button class=”github-btn” href=”http://frontcast.ir/async-javascript”]ویدیوی آموزشی: فرآیندهای Asynchronous در جاوااسکریپت[/button]
دو نوع Scope (محدوده) در جاوااسکریپت وجود دارد. Scope محلی و Scope سراسری. متغیری که Scope محلی دارد تنها در قسمت مشخص و محدودی از کد قابل استفاده است. در حالی که متغیر سراسری در تمام قسمتهای کد قابل استفاده است.
// Global scope const globalCow = ‘global cow’; const showCow = () => { const localCow = ‘local cow’; return globalCow; }; const clonedCow = globalCow; const mixedCow = globalCow + localCow; // error: Uncaught ReferenceError: localCow is not defined
همانطور که در مثال بالا میبینید، متغیر globalCow در هر جایی از کد حتی در داخل محتوای محلی تابع showCow استفاده شده است. اما نمیتوانیم متغیر محلی localCow را خارج از تابع showCow که در آن به صورت محلی تعریف شدهاست، استفاده کنیم.
[button class=”github-btn” href=”http://frontcast.ir/scope-in-javascript”]ویدیوی آموزشی: درک بهتر Scope در جاوااسکریپت[/button]
مقداردهی (value) به متغیرها به همان آسانی که به نظر میرسد، نیست. باید توجه کنیم که هنگام مقداردهی به متغیر ها، لازم است مطمئن شویم که مقدارهای واقعی هستند یا به منابع و محل حافظه اشاره دارند. در غیر این صورت، این احتمال وجود دارد که مقادیر را ناخواسته تغییر دهید.
زمانی که از انواع اصلی مانند رشته، اعداد یا مقادیر Boolian استفاده میکنید، معمولا مشکلی به وجود نمی آید چرا که اینها مقادیر واقعی هستند. اما زمانی که object، آرایه یا توابع را استفاده کنید این مسئله قدری پیچیدهتر میشود. چراکه در این مواقع، متغیر مقدار واقعی را نگهداری نمیکند بلکه به مقدار واقعی موجود در حافظه اشاره (reference) میکند.
let num1 = 1; let num2 = num1; // Changing num2’s value does not change num1’s value num2 = 4; console.log(num1); // 1 console.log(num2); // 4 let arr1 = [‘Amy’, ‘John’]; let arr2 = arr1; // Changing elements’ value in arr2 leads to changing elements’ value in arr1 arr2[0] = ‘Jane’; console.log(arr1); // [“Jane”, “John”] console.log(arr2); // [“Jane”, “John”]
در جاوااسکریپت، یک تابع callback، تابعی است که پس از فراخوانی تابع دیگری اجرا میشود و میتوان این تابع را به عنوان پارامتر برای سایر توابع استفاده کرد.
در حالت نرمال کدی که مینویسیم به ترتیب از بالا به پایین اجرا میشود. در حالی که برخی تسکها وجود دارند که لازم است قبل از اجرای بقیه تسکها اجرا شوند. در چنین وضعیتی از تابع callback استفاده میکنیم.
const fetchUsers = callback => { setTimeout(() => { let response = ‘[{name: “Amy”}, {name: “John”}]’; callback(response); }, ۵۰۰); }; const showUsers = users => console.log(users); fetchUsers(showUsers);
در مثال فوق، تابع fetchUsers را فراخوانی کرده و تابع callback با نام showUsers را به عنوان پارامتر به آن میدهیم. زمانی که تمام دادهها به طور کامل بارگذاری شوند، تابع showUsers آنها را نمایش خواهد داد.
هروقت که در جاوااسکریپت یک تابع یا آبجکت بسازیم ویژگی prototype به آنها اضافه خواهد شد. Prototype یک آبجکت است که به طور پیشفرض با توابع و آبجکتها مرتبط است و در آن میتوانیم ویژگیهای دیگری را که میتوانند توسط آبجکتهای دیگر به ارث برسند، به آن تابع یا آبجکت اضافه کنیم.
function Person() { this.name = ‘Amy’; this.age = 28; } Person.prototype.job = ‘Programmer’; Person.prototype.showName = function() { console.log(‘My name is ‘ + this.name); } let person = new Person(); person.showName(); // My name is Amy
قبل از ES6 در جاوااسکریپت مفهوم کلاس وجود نداشت و تنها میتوانستیم با استفاده از یک روش تابعی به مفهومی شبیه کلاس دست یابیم.
function Book(title) { this.title = title; } Book.prototype.showTitle = function() { console.log(this.title); }; let book = new Book(‘JavaScript’); book.showTitle(); // JavaScript
در ES6 میتوانیم کلاس واقعی را مشابه مثال زیر، شبیه هر زبان مبتنی بر کلاس دیگری ایجاد کنیم:
class Book { constructor(title) { this.title = title; } showBook() { console.log(this.title); } } let book = new Book(‘ES6’); book.showBook();
[button class=”github-btn” href=”http://frontcast.ir/procedural-oop-functional”]ویدیوی آموزشی: برنامه نویسی رویهای، شیگرا و تابعی[/button]
یک روش ساده برای دریافت مقادیر آبجکتها است.
مثال زیر یک استفاده متداول از این مفهوم را نشان میدهد:
const person = { name: ‘Amy’, age: 28 }; let { name, age } = person; console.log(name); // Amy console.log(age); // 28
می توانید متغیرها را مثل نام ویژگیها شبیه کد فوق نگه دارید یا متغیرهای جدیدی تعریف کنید:
let { name: newName, age: newAge } = person; console.log(newName); // Amy console.log(newAge); // 28
این مفهوم به شما امکان دسترسی به قسمتهای داخلی یک آبجکت را میدهد. به عبارتی، یک روش سریع و مختصر برای افزودن آیتمهای جدید به آرایهها، ترکیب آبجکتها یا بیرون کشیدن آیتم از آرایه و انتقال آن ها به یک تابع است.
// Combining Arrays let arr1 = [1, 2, 3]; let arr2 = [4, 5, 6]; let arr3 = […arr1, …arr2]; console.log(arr3); // [1, 2, 3, 4, 5, 6] // Combining Objects let obj1 = { name: ‘Amy’, age: 28 }; let obj2 = { job: ‘programmer’ }; let obj3 = { …obj1, …obj2 }; console.log(obj3); // {name: “Amy”, age: 28, job: “programmer”} // Spreading out an array and pass it to a function const sum = (…arr) => { const length = arr.length; let sum = 0; for (let i = 0; i < length; i++) { sum += arr[i]; } return sum; }; let arr = [3, 5, 3, 2, 1]; console.log(sum(…arr)); // 14 console.log(sum(3, 5, 4, 1)); // 13
برای درک بهتر و بررسی جامع مفاهیم جاوااسکریپت، دوره جامع و پیشرفته جاوااسکریپت فرانت کست را پیشنهاد میکنیم.