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

JavaScript ArrayBuffer.isView() - ตรวจสอบ ArrayBuffer View


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

ArrayBuffer.isView(arg) เป็น static method ที่ตรวจสอบว่า argument ที่ส่งเข้ามาเป็น ArrayBuffer View (TypedArray หรือ DataView) หรือไม่ คืนค่า true / false

ArrayBuffer Views ที่ตรวจสอบได้

  • TypedArrays: Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, BigInt64Array, BigUint64Array
  • DataView
  • ไม่รวม: ArrayBuffer ตัวเอง, plain Array, Object, null, undefined

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

<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>ArrayBuffer.isView() 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; 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; }
    .true { color: #2e7d32; font-weight: bold; }
    .false { color: #c62828; font-weight: bold; }
  </style>
</head>
<body>
  <h1>ArrayBuffer.isView() - ตรวจสอบ TypedArray / DataView</h1>
  
  <div class="panel">
    <h3>ทดสอบค่าต่างๆ</h3>
    <button onclick="testAll()">ทดสอบทั้งหมด</button>
    <button onclick="testCustom()">ทดสtoverride Custom Object</button>
  </div>
  
  <div class="panel">
    <h3>ผลลัพธ์</h3>
    <div class="output" id="output"></div>
  </div>

  <script>
    const output = document.getElementById('output');
    
    function log(msg, isView = null) {
      const div = document.createElement('div');
      div.textContent = msg;
      if (isView === true) div.className = 'true';
      else if (isView === false) div.className = 'false';
      output.appendChild(div);
    }
    
    function clear() { output.innerHTML = ''; }
    
    function testAll() {
      clear();
      
      // สร้าง ArrayBuffer และ Views ต่างๆ
      const buffer = new ArrayBuffer(16);
      
      const testCases = [
        { name: 'ArrayBuffer (16 bytes)', value: buffer },
        { name: 'Int8Array', value: new Int8Array(buffer) },
        { name: 'Uint8Array', value: new Uint8Array(buffer) },
        { name: 'Uint8ClampedArray', value: new Uint8ClampedArray(buffer) },
        { name: 'Int16Array', value: new Int16Array(buffer) },
        { name: 'Uint16Array', value: new Uint16Array(buffer) },
        { name: 'Int32Array', value: new Int32Array(buffer) },
        { name: 'Uint32Array', value: new Uint32Array(buffer) },
        { name: 'Float32Array', value: new Float32Array(buffer) },
        { name: 'Float64Array', value: new Float64Array(buffer) },
        { name: 'BigInt64Array', value: typeof BigInt64Array !== 'undefined' ? new BigInt64Array(buffer) : 'N/A' },
        { name: 'BigUint64Array', value: typeof BigUint64Array !== 'undefined' ? new BigUint64Array(buffer) : 'N/A' },
        { name: 'DataView', value: new DataView(buffer) },
        { name: 'Plain Array []', value: [1, 2, 3] },
        { name: 'Plain Object {}', value: {} },
        { name: 'null', value: null },
        { name: 'undefined', value: undefined },
        { name: 'String', value: 'hello' },
        { name: 'Number', value: 123 },
      ];
      
      log('=== ArrayBuffer.isView() Test Results ===\n');
      
      testCases.forEach(({ name, value }) => {
        if (value === 'N/A') {
          log(`${name}: Not supported in this environment`);
          return;
        }
        const result = ArrayBuffer.isView(value);
        log(`${name}: ${result}`, result);
      });
    }
    
    function testCustom() {
      clear();
      log('=== Custom Objects with Symbol.toStringTag ===\n');
      
      // Object ปกติ - ไม่ใช่ view
      const obj = {};
      log(`Plain object: ${ArrayBuffer.isView(obj)}`, false);
      
      // Object ที่ pretend เป็น TypedArray (แต่ไม่ได้จริง)
      const fakeView = {
        buffer: new ArrayBuffer(8),
        byteLength: 8,
        byteOffset: 0,
        [Symbol.toStringTag]: 'Int32Array'
      };
      log(`Fake TypedArray (with toStringTag): ${ArrayBuffer.isView(fakeView)}`, false);
      
      // Subclass ของ TypedArray
      class MyInt32Array extends Int32Array {}
      const myView = new MyInt32Array(4);
      log(`MyInt32Array (extends Int32Array): ${ArrayBuffer.isView(myView)}`, true);
      
      // DataView subclass
      class MyDataView extends DataView {}
      const myDV = new MyDataView(new ArrayBuffer(8));
      log(`MyDataView (extends DataView): ${ArrayBuffer.isView(myDV)}`, true);
    }
    
    testAll();
  </script>
</body>
</html>

ผลลัพธ์ที่คาดหวัง

ArrayBuffer (16 bytes): false
Int8Array: true
Uint8Array: true
Uint8ClampedArray: true
Int16Array: true
Uint16Array: true
Int32Array: true
Uint32Array: true
Float32Array: true
Float64Array: true
BigInt64Array: true
BigUint64Array: true
DataView: true
Plain Array []: false
Plain Object {}: false
null: false
undefined: false
String: false
Number: false

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

1. Type Guard ใน TypeScript / JSDoc

function processBuffer(data: ArrayBuffer | ArrayBufferView) {
  if (ArrayBuffer.isView(data)) {
    // TypeScript รู้ว่า data เป็น TypedArray หรือ DataView
    console.log('Byte length:', data.byteLength);
    console.log('Byte offset:', data.byteOffset);
  } else {
    // data เป็น ArrayBuffer
    console.log('Buffer size:', data.byteLength);
  }
}

2. Validation ฟังก์ชันที่รับ Binary Data

function writeToBuffer(view, offset, value) {
  if (!ArrayBuffer.isView(view)) {
    throw new TypeError('Expected ArrayBufferView (TypedArray or DataView)');
  }
  if (offset < 0 || offset + 4 > view.byteLength) {
    throw new RangeError('Offset out of bounds');
  }
  new DataView(view.buffer, view.byteOffset + offset).setInt32(0, value);
}

3. Serialize/Deserialize Binary Data

function cloneBufferView(view) {
  if (!ArrayBuffer.isView(view)) {
    throw new Error('Not a buffer view');
  }
  // สร้าง buffer ใหม่และ copy ข้อมูล
  const newBuffer = new ArrayBuffer(view.byteLength);
  const newView = new view.constructor(newBuffer);
  newView.set(view);
  return newView;
}

ความแตกต่าง: ArrayBuffer vs ArrayBufferView

คุณสมบัติArrayBufferArrayBufferView (TypedArray/DataView)
เก็บข้อมูลจริงใช่ (Raw binary data)ไม่ (Reference/Window into buffer)
isView()falsetrue
byteLengthขนาดทั้งหมดขนาดของ view นี้
byteOffsetN/Aตำแหน่งเริ่มต้นใน buffer
buffer propertyN/Aอ้างอิง ArrayBuffer ต้นทาง
Manipulationไม่ได้โดยตรงอ่าน/เขียนผ่าน TypedArray/DataView

Browser Support

  • Chrome 7+, Firefox 4+, Safari 5.1+, Edge 12+, IE 10+
  • รองรับเต็มรูปแบบในทุกเบราว์เซอร์สมัยใหม่