ArrayBuffer.prototype.byteLength คืออะไร?
byteLength เป็น read-only property ของ ArrayBuffer ที่คืนค่าขนาดของ buffer ในหน่วย Bytes (ไบต์) กำหนดตอนสร้างและไม่สามารถเปลี่ยนแปลงได้
ตัวอย่างโค้ดครบถ้วน
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ArrayBuffer.byteLength</title>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
.panel { background: #f5f5f5; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
.code { background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 4px; font-family: monospace; overflow-x: auto; }
.output { background: #e8f5e9; padding: 15px; border-radius: 4px; font-family: monospace; white-space: pre-wrap; }
button { padding: 10px 20px; background: #7e32d4; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 10px; margin-bottom: 10px; }
button:hover { background: #6a1b9a; }
table { width: 100%; border-collapse: collapse; margin-top: 10px; }
th, td { padding: 10px; border: 1px solid #ddd; text-align: left; }
th { background: #7e32d4; color: white; }
.view-info { background: white; padding: 15px; border-radius: 4px; margin: 10px 0; border-left: 4px solid #7e32d4; }
</style>
</head>
<body>
<h1>ArrayBuffer.prototype.byteLength</h1>
<p>คุณสมบัติอ่านอย่างเดียวที่คืนขนาดของ Array Buffer ในหน่วย Bytes</p>
<div class="panel">
<h3>ทดสอบขนาด Buffer ต่างๆ</h3>
<button onclick="demoBasic()">Basic Sizes</button>
<button onclick="demoViews()">Views & Offsets</button>
<button onclick="demoResize()">Resize (Transfer)</button>
</div>
<div class="panel">
<h3>ผลลัพธ์</h3>
<div class="output" id="output"></div>
</div>
<script>
const output = document.getElementById('output');
function log(msg) {
output.textContent += msg + '\n';
}
function clear() { output.textContent = ''; }
function demoBasic() {
clear();
log('=== ArrayBuffer byteLength ===\n');
const sizes = [0, 1, 8, 16, 64, 1024, 1024 * 1024]; // 0, 1B, 8B, 16B, 64B, 1KB, 1MB
sizes.forEach(size => {
const buffer = new ArrayBuffer(size);
log(`new ArrayBuffer(${size}) → byteLength: ${buffer.byteLength} bytes (${formatBytes(buffer.byteLength)})`);
});
log('\n--- Max Size ---');
try {
const maxBuffer = new ArrayBuffer(Number.MAX_SAFE_INTEGER);
log(`Max safe: ${maxBuffer.byteLength} bytes`);
} catch (e) {
log(`Max size limited by engine: ${e.message}`);
}
}
function demoViews() {
clear();
log('=== Views share buffer.byteLength ===\n');
const buffer = new ArrayBuffer(32); // 32 bytes
log(`Original Buffer: ${buffer.byteLength} bytes\n`);
const views = [
{ name: 'Int8Array (1 byte each)', view: new Int8Array(buffer) },
{ name: 'Uint16Array (2 bytes each)', view: new Uint16Array(buffer) },
{ name: 'Int32Array (4 bytes each)', view: new Int32Array(buffer) },
{ name: 'Float64Array (8 bytes each)', view: new Float64Array(buffer) },
{ name: 'DataView', view: new DataView(buffer) }
];
views.forEach(({ name, view }) => {
log(`${name}:`);
log(` view.byteLength = ${view.byteLength} bytes`);
log(` view.byteOffset = ${view.byteOffset}`);
log(` view.buffer.byteLength = ${view.buffer.byteLength} bytes`);
log(` Elements: ${view.byteLength / (view.BYTES_PER_ELEMENT || 1)}`);
log('');
});
// View with offset
log('--- View with Offset ---');
const offsetView = new Int32Array(buffer, 8, 4); // เริ่มที่ byte 8, ยาว 4 elements (16 bytes)
log(`new Int32Array(buffer, 8, 4):`);
log(` byteLength: ${offsetView.byteLength} (4 elements × 4 bytes)`);
log(` byteOffset: ${offsetView.byteOffset}`);
log(` buffer.byteLength: ${offsetView.buffer.byteLength} (unchanged)`);
}
function demoResize() {
clear();
log('=== Resizing ArrayBuffer (Resizable - ES2024) ===\n');
// Standard ArrayBuffer - ไม่ resize ได้
const fixedBuffer = new ArrayBuffer(100);
log(`Fixed buffer: ${fixedBuffer.byteLength} bytes`);
log('Cannot resize fixed ArrayBuffer\n');
// Resizable ArrayBuffer (ES2024 / Stage 3)
if (typeof ArrayBuffer.prototype.resize === 'function') {
const resizable = new ArrayBuffer(100, { maxByteLength: 1000 });
log(`Resizable buffer: ${resizable.byteLength} / max ${resizable.maxByteLength} bytes`);
log(`resizable.resize(200) → `);
resizable.resize(200);
log(` New byteLength: ${resizable.byteLength}`);
log(`resizable.resize(50) → `);
resizable.resize(50);
log(` New byteLength: ${resizable.byteLength}`);
} else {
log('Resizable ArrayBuffer not supported in this environment');
log('Polyfill: ใช้ ArrayBuffer.transfer() หรือสร้างใหม่ + copy');
}
}
function formatBytes(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
}
demoBasic();
</script>
</body>
</html>
ความสัมพันธ์ระหว่าง Buffer และ Views
const buffer = new ArrayBuffer(16); // 16 bytes // Views ต่างๆ มอง buffer เดียวกัน แต่ byteLength ต่างกัน new Int8Array(buffer).byteLength // 16 (16 elements × 1 byte) new Int16Array(buffer).byteLength // 16 (8 elements × 2 bytes) new Int32Array(buffer).byteLength // 16 (4 elements × 4 bytes) new Float64Array(buffer).byteLength // 16 (2 elements × 8 bytes) new DataView(buffer).byteLength // 16 (full buffer) // View with offset/length new Int32Array(buffer, 4, 2).byteLength // 8 (2 elements × 4 bytes, เริ่มที่ byte 4) new DataView(buffer, 8).byteLength // 8 (จาก byte 8 ถึงสิ้นสุด)
ArrayBuffer vs View byteLength
| Property | ArrayBuffer | TypedArray / DataView |
|---|---|---|
byteLength | ขนาด buffer ทั้งหมด (fixed) | ขนาดของ view นี้ (อาจน้อยกว่า buffer) |
byteOffset | N/A | ตำแหน่งเริ่มต้นใน buffer (bytes) |
buffer | N/A | อ้างอิง ArrayBuffer ต้นทาง |
| Mutable | ไม่ (standard) / ใช่ (resizable) | ข้อมูล mutable, แต่ view metadata immutable |
Resizable ArrayBuffer (ES2024 / Stage 3)
// สร้าง resizable buffer
const buffer = new ArrayBuffer(100, { maxByteLength: 1000 });
console.log(buffer.byteLength); // 100
console.log(buffer.maxByteLength); // 1000
console.log(buffer.resizable); // true
// ขยาย
buffer.resize(500);
console.log(buffer.byteLength); // 500
// หด
buffer.resize(50);
console.log(buffer.byteLength); // 50
// ไม่สามารถเกิน maxByteLength
buffer.resize(2000); // RangeError
การประยุกต์ใช้จริง
1. ตรวจสอบขนาดก่อนอ่าน/เขียน
function readInt32(view, offset) {
if (offset + 4 > view.byteLength) {
throw new RangeError(`Offset ${offset} out of bounds (length: ${view.byteLength})`);
}
return new DataView(view.buffer, view.byteOffset + offset).getInt32(0);
}
2. คำนวณจำนวน Elements
function getElementCount(view) {
return view.byteLength / view.BYTES_PER_ELEMENT;
}
const arr = new Float32Array(100);
console.log(getElementCount(arr)); // 100
3. Memory Monitoring
function getMemoryUsage(buffers) {
return buffers.reduce((sum, buf) => sum + buf.byteLength, 0);
}
const buffers = [new ArrayBuffer(1024), new ArrayBuffer(2048)];
console.log(`Total: ${getMemoryUsage(buffers)} bytes`); // 3072
Browser Support
byteLength: ทุกเบราว์เซอร์รองรับ (IE10+)resizable ArrayBuffer: Chrome 122+, Firefox 127+, Safari 17.4+ (ES2024)ArrayBuffer.transfer(): Chrome 113+ (Transferable, zero-copy)