ArrayBuffer و Typed Array: کار مستقیم با داده‌ی باینری در جاوااسکریپت

آرایه‌های معمولی جاوااسکریپت بسیار انعطاف‌پذیرند: می‌توانند هم‌زمان انواع مختلف داده را نگه دارند و اندازه‌شان به‌راحتی تغییر می‌کند. اما همین انعطاف‌پذیری، هزینه‌ای در عملکرد و مصرف حافظه به همراه دارد که در کارهایی مثل پردازش تصویر، فایل‌های صوتی، یا ارتباط با WebSocket به‌صورت باینری، قابل‌توجه می‌شود. برای این نوع نیازها، جاوااسکریپت ArrayBuffer و Typed Array را ارائه می‌دهد.

ArrayBuffer: یک بلوک خام از حافظه

ArrayBuffer یک ناحیه‌ی خام و با اندازه‌ی ثابت از حافظه را نشان می‌دهد که برحسب بایت اندازه‌گیری می‌شود. نکته‌ی مهم این است که خود ArrayBuffer هیچ راهی برای خواندن یا نوشتن مستقیم مقدار در خود ندارد؛ فقط یک فضای خالی رزرو‌شده در حافظه است:

const buffer = new ArrayBuffer(16); // یک بافر ۱۶ بایتی
console.log(buffer.byteLength); // 16

// buffer[0] = 1; // این کار هیچ اثری ندارد؛ ArrayBuffer مستقیماً قابل نوشتن نیست

Typed Array: پنجره‌ای برای خواندن و نوشتن روی ArrayBuffer

برای واقعاً کار کردن با محتوای یک ArrayBuffer، باید از یکی از Typed Arrayها استفاده کرد؛ ساختارهایی که هرکدام نوع و اندازه‌ی مشخصی از داده‌ی عددی را تعریف می‌کنند و مثل یک «دیدگاه» (view) روی همان حافظه‌ی خام عمل می‌کنند:

خواندن و نوشتن با Typed Array
خروجی کنسول اینجا نمایش داده می‌شود...

نکته‌ی کلیدی این مثال این است که view و bytesView هر دو به یک buffer واحد اشاره دارند، فقط با نوع داده‌ی متفاوت آن را می‌خوانند. تغییر مقدار از طریق یکی، بلافاصله در دیگری نیز قابل مشاهده است، چون هر دو در واقع همان حافظه‌ی خام را نمایش می‌دهند.

انواع رایج Typed Array

نوع اندازه‌ی هر عنصر بازه‌ی مقدار
Int8Array ۱ بایت -128 تا 127
Uint8Array ۱ بایت 0 تا 255
Int32Array ۴ بایت حدود -۲ میلیارد تا +۲ میلیارد
Float64Array ۸ بایت اعداد اعشاری با دقت مضاعف

ساخت مستقیم Typed Array بدون ArrayBuffer دستی

در بسیاری از موارد، نیازی به ساخت جداگانه‌ی ArrayBuffer نیست؛ Typed Arrayها می‌توانند مستقیماً با طول مشخص یا از روی یک آرایه‌ی معمولی ساخته شوند و خودشان بافر لازم را در پس‌زمینه می‌سازند:

const scores = new Float64Array([98.5, 76.2, 88.9]);

console.log(scores[0]);       // 98.5
console.log(scores.length);   // 3
console.log(scores.buffer);   // ArrayBuffer به‌طور خودکار ساخته‌شده در پس‌زمینه

برخلاف آرایه‌ی معمولی، طول یک Typed Array پس از ساخت ثابت است و امکان افزودن یا حذف عنصر با متدهایی مثل push یا pop وجود ندارد؛ این محدودیت دقیقاً همان دلیلی است که Typed Array را از نظر عملکرد و پیش‌بینی‌پذیری حافظه، برتر از آرایه‌ی معمولی می‌کند.

چرا این ابزارها اهمیت دارند؟

Typed Arrayها پایه‌ی بسیاری از APIهای مدرن مرورگر هستند که با داده‌ی باینری سروکار دارند؛ از جمله WebSocket برای ارسال و دریافت داده‌ی باینری، Canvas برای دسترسی مستقیم به پیکسل‌های تصویر، و Web Audio API برای پردازش سیگنال صوتی. در این موارد، سرعت و کارایی حافظه اهمیت بسیار بیشتری نسبت به انعطاف‌پذیری آرایه‌ی معمولی دارد.

نکات کلیدی

  • ArrayBuffer یک ناحیه‌ی خام و با اندازه‌ی ثابت از حافظه است که مستقیماً قابل خواندن یا نوشتن نیست.
  • Typed Array مثل یک دیدگاه (view) روی ArrayBuffer عمل می‌کند و امکان خواندن و نوشتن داده‌های عددی با نوع مشخص را فراهم می‌کند.
  • چند Typed Array مختلف می‌توانند هم‌زمان روی یک ArrayBuffer واحد، با تفسیرهای متفاوتی از همان بایت‌ها، عمل کنند.
  • طول یک Typed Array پس از ساخت ثابت است و متدهایی مثل push یا pop روی آن قابل استفاده نیستند.

جمع‌بندی

ArrayBuffer و Typed Array دسترسی مستقیم، سریع و کارآمد به حافظه را برای داده‌های عددی و باینری در جاوااسکریپت فراهم می‌کنند، در ازای انعطاف‌پذیری کمتر نسبت به آرایه‌ی معمولی. این ابزارها معمولاً به‌طور مستقیم در کد روزمره کمتر دیده می‌شوند، اما زیربنای APIهای پیشرفته‌ای مثل WebSocket، Canvas و Web Audio هستند که در پروژه‌های تخصصی‌تر با آن‌ها سروکار خواهید داشت.