Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

JavaScript ArrayBuffer.slice() Method - การสลายนำ ArrayBuffer


ArrayBuffer.slice() คืออะไร?

ArrayBuffer.prototype.slice(begin, end) สร้าง ArrayBuffer ใหม่ ที่เป็นสำเนาของข้อมูลบाइनะรี่จากตำแหน่ง begin (inclusive) ถึง end (exclusive) คล้ายกับ Array.slice() แต่ทำงานกับ binary data

Syntax

arrayBuffer.slice(begin[, end])
  • begin - index เริ่มต้น (0-based) รวมตัวเอง
  • end (optional) - index สิ้นสุด ไม่รวมตัวเอง | default = byteLength
  • คืนค่า: ArrayBuffer ใหม่ (ไม่เปลี่ยนตัวเดิม)
  • รองรับ negative index (นับจากท้าย)

ตัวอย่างโค้ดครบถ้วน

<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>ArrayBuffer.slice() Demo</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; }
    button:hover { background: #6a1b9a; }
    table { width: 100%; border-collapse: collapse; margin-top: 10px; }
    th, td { padding: 8px; border: 1px solid #ddd; text-align: center; }
    th { background: #7e32d4; color: white; }
  </style>
</head>
<body>
  <h1>ArrayBuffer.slice() Demo</h1>
  
  <div class="panel">
    <h3>สร้าง ArrayBuffer 16 bytes (4 จำนวน Int32)</h3>
    <button onclick="createBuffer()">สร้าง Buffer ใหม่</button>
    <button onclick="demoSlice()">Slice (0, 8) - copy 8 bytes แรก</button>
    <button onclick="demoSliceNegative()">Slice (-8) - copy 8 bytes หลัง</button>
    <button onclick="demoSliceRange()">Slice (4, 12) - copy กลาง</button>
  </div>
  
  <div class="panel">
    <h3>Original Buffer (Int32 View)</h3>
    <div class="code" id="originalView"></div>
  </div>
  
  <div class="panel">
    <h3>Sliced Buffer Result</h3>
    <div class="output" id="slicedOutput"></div>
  </div>

  <script>
    let buffer = null;
    let int32View = null;
    const originalView = document.getElementById('originalView');
    const slicedOutput = document.getElementById('slicedOutput');
    
    function createBuffer() {
      buffer = new ArrayBuffer(16); // 16 bytes = 4 Int32 (4 bytes each)
      int32View = new Int32Array(buffer);
      int32View[0] = 0x11223344;
      int32View[1] = 0x55667788;
      int32View[2] = 0x99AABBCC;
      int32View[3] = 0xDDEEFF00;
      
      originalView.textContent = 'Buffer byteLength: ' + buffer.byteLength + '\n' +
        'Int32Array: [' + Array.from(int32View).map(v => '0x' + v.toString(16).toUpperCase().padStart(8, '0')).join(', ') + ']';
      slicedOutput.textContent = 'ยังไม่ได้ slice';
    }
    
    function showSliceResult(slicedBuffer, label) {
      const view = new Int32Array(slicedBuffer);
      slicedOutput.textContent = `${label}\n` +
        `byteLength: ${slicedBuffer.byteLength} bytes\n` +
        `Int32Array: [${Array.from(view).map(v => '0x' + v.toString(16).toUpperCase().padStart(8, '0')).join(', ')}]`;
    }
    
    function demoSlice() {
      if (!buffer) { alert('สร้าง Buffer ก่อน'); return; }
      // copy 8 bytes แรก (2 Int32 แรก)
      const sliced = buffer.slice(0, 8);
      showSliceResult(sliced, 'slice(0, 8) - 8 bytes แรก:');
    }
    
    function demoSliceNegative() {
      if (!buffer) { alert('สร้าง Buffer ก่อน'); return; }
      // copy 8 bytes หลัง (2 Int32 หลัง) - negative index
      const sliced = buffer.slice(-8);
      showSliceResult(sliced, 'slice(-8) - 8 bytes หลัง:');
    }
    
    function demoSliceRange() {
      if (!buffer) { alert('สร้าง Buffer ก่อน'); return; }
      // copy bytes 4-11 (Int32 index 1 และ 2)
      const sliced = buffer.slice(4, 12);
      showSliceResult(sliced, 'slice(4, 12) - bytes 4-11:');
    }
    
    createBuffer();
  </script>
</body>
</html>

การทำงานของ Slice

Original Buffer (16 bytes):
Index:  0    1    2    3    4    5    6    7    8    9    10   11   12   13   14   15
Value: 44  33  22  11   88  77  66  55   CC  BB  AA  99   00  FF  EE  DD  (Little Endian)

Int32 View: [0x11223344, 0x55667788, 0x99AABBCC, 0xDDEEFF00]

slice(0, 8)    → bytes 0-7   → Int32: [0x11223344, 0x55667788]     (2 elements)
slice(4, 12)   → bytes 4-11  → Int32: [0x55667788, 0x99AABBCC]     (2 elements)  
slice(-8)      → bytes 8-15  → Int32: [0x99AABBCC, 0xDDEEFF00]     (2 elements)
slice()        → bytes 0-15  → Int32: [0x11223344, 0x55667788, 0x99AABBCC, 0xDDEEFF00] (copy ทั้งหมด)

กรณีการใช้งานจริง (Use Cases)

  • Binary Protocol Parsing: ตัด header/payload ออกจาก buffer ที่รับมาจาก network
  • File Processing: อ่านเฉพาะส่วนของไฟล์ใหญ่ (chunked reading)
  • WebGL/WebGPU: สร้าง sub-buffer สำหรับ vertex/index buffers
  • Audio/Video: ตัด frame หรือ sample จาก buffer
  • Crypto: แยก salt, IV, ciphertext จาก encrypted buffer

ความแตกต่างกับ TypedArray.subarray()

คุณสมบัติArrayBuffer.slice()TypedArray.subarray()
คืนค่าArrayBuffer ใหม่ (copy ข้อมูล)TypedArray view ใหม่ (shared memory - zero copy)
Memoryจองหน่วยความจำใหม่ไม่จองหน่วยความจำใหม่ (เร็วกว่า)
ใช้เมื่อต้องการ buffer แยกต่างหาก (isolated)ต้องการ view ตัวแปรของข้อมูลเดิม
Available onArrayBufferInt8Array, Uint8Array, Int32Array, Float32Array, etc.

ตัวอย่าง subarray (Zero-copy)

const buffer = new ArrayBuffer(16);
const view = new Int32Array(buffer);
view[0] = 1; view[1] = 2; view[2] = 3; view[3] = 4;

const sub = view.subarray(1, 3); // Int32Array [2, 3] - ใช้ memory เดียวกัน!
sub[0] = 999;
console.log(view[1]); // 999 - เปลี่ยนค่าตัวเดิมด้วย!