משתמשים ב-ArrayBuffers כדי להעביר נתונים גולמיים, ומספר ממשקי API חדשים מסתמכים עליהם, כולל WebSockets, Web Intents 2 (https://www.html5rocks.com/en/tutorials/file/xhr2/) ו-WebWorkers. עם זאת, מכיוון שהן הגיעו לאחרונה לעולם JavaScript, לפעמים הן מובנות בצורה שגויה או נעשה בהן שימוש לרעה.
מבחינה סמנטית, ArrayBuffer הוא פשוט מערך של בייטים שמוצגים דרך מסכה ספציפית.
המסכה הזו, מופע של ArrayBufferView, מגדירה את אופן היישור של הבייטים כך שיתאים למבנה הצפוי של התוכן. לדוגמה, אם אתם יודעים שהבייטים ב-ArrayBuffer מייצגים מערך של מספרים שלמים לא חתומים באורך 16 ביט, אתם יכולים פשוט לעטוף את ה-ArrayBuffer בתצוגה של Uint16Array
ולבצע פעולות על הרכיבים שלו באמצעות תחביר הסוגריים כאילו Uint16Array
הוא מערך של מספרים שלמים:
// suppose buf contains the bytes [0x02, 0x01, 0x03, 0x07]
// notice the multibyte values respect the hardware endianess, which is little-endian in x86
var bufView = new Uint16Array(buf);
if (bufView[0]===258) { // 258 === 0x0102
console.log("ok");
}
bufView[0] = 255; // buf now contains the bytes [0xFF, 0x00, 0x03, 0x07]
bufView[0] = 0xff05; // buf now contains the bytes [0x05, 0xFF, 0x03, 0x07]
bufView[1] = 0x0210; // buf now contains the bytes [0x05, 0xFF, 0x10, 0x02]
שאלה מעשית נפוצה לגבי ArrayBuffer היא איך ממירים String
ל-ArrayBuffer
ולהפך. מכיוון ש-ArrayBuffer הוא למעשה מערך בייטים, ההמרה הזו מחייבת את שני הצדדים להסכים איך לייצג את התווים במחרוזת כבייטים. סביר להניח שכבר נתקלתם ב'הסכם' הזה בעבר: זהו קידוד התווים של המחרוזת (ו'תנאי ההסכם' הרגילים הם, למשל, Unicode UTF-16 ו-iso8859-1). לכן, אם הסכמתם עם הצד השני על קידוד UTF-16, קוד ההמרה יכול להיות משהו כזה:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
שימו לב לשימוש ב-Uint16Array
. זוהי תצוגה של ArrayBuffer שמיישרת את הבייטים של ה-ArrayBuffers בתור אלמנטים של 16 ביט. הוא לא מטפל בקידוד התווים עצמו, ש-String.fromCharCode
ו-str.charCodeAt
מטפלים בו כ-Unicode.
בשאלה הפופולרית הזו ב-StackOverflow יש תשובה שזכתה לפופולריות רבה עם פתרון מעט מסובך להמרה: יוצרים FileReader
שישמש כממיר ומזינים בו Blob
שמכיל את המחרוזת. השיטה הזו פועלת, אבל קשה לקרוא אותה ויש להניח שהיא איטית. מאחר שחשדות לא מבוססים הובילו לטעויות רבות בהיסטוריה של האנושות, נשתמש כאן בגישה מדעית יותר. בדקתי את שתי השיטות באמצעות jsperf והתוצאה מאשרת את החשד שלי. אפשר לבדוק את הדמו כאן.
ב-Chrome 20, השימוש בקוד הטיפול ישירות ב-ArrayBuffer
שמתואר במאמר הזה מהיר כמעט פי 27 מהשימוש בשיטה FileReader
/Blob
.