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

คุณสมบัติ DataView.byteOffset ใน JavaScript

DataView.byteOffset คืออะไร

คุณสมบัติ DataView.prototype.byteOffset เป็นคุณสมบัติแบบอ่านอย่างเดียว (read-only) ที่คืนค่า ตำแหน่งเริ่มต้น (offset ในหน่วยไบต์) ของ DataView นี้ เทียบกับจุดเริ่มต้นของ ArrayBuffer ต้นฉบับ (view.buffer)

หมายเหตุ: เอกสารต้นฉบับเขียนว่า dataView.byteOffset() พร้อมวงเล็บ ซึ่ง ไม่ถูกต้อง - byteOffset เป็น property (คุณสมบัติ) ไม่ใช่ method (เมธод) จึงเรียกใช้ โดยไม่ต้องมีวงเล็บ

ไวยากรณ์ (Syntax)

dataView.byteOffset

คืนค่า: จำนวนเต็มไม่มีเครื่องหมาย แทน offset ในหน่วยไบต์

ตัวอย่างการใช้งาน

ตัวอย่างที่ 1: DataView เริ่มต้นที่ 0 (Default)

const buffer = new ArrayBuffer(114);
const view = new DataView(buffer); // ไม่ระบุ offset -> 0

console.log(view.byteOffset);       // 0
console.log(view.buffer.byteLength); // 114
console.log(view.byteLength);       // 114 (เท่ากับ buffer ทั้งหมด)

ตัวอย่างที่ 2: DataView ที่มี Offset และ Length เฉพาะ

const buffer = new ArrayBuffer(100);
const view = new DataView(buffer, 20, 30);

console.log(view.byteOffset);       // 20
console.log(view.byteLength);       // 30
console.log(view.buffer.byteLength); // 100

ตัวอย่างที่ 3: Multiple Views บน Buffer เดียว

const buffer = new ArrayBuffer(64);

// View แรก: 32 ไบต์แรก
const headerView = new DataView(buffer, 0, 32);
console.log('Header:', headerView.byteOffset, headerView.byteLength); // 0, 32

// View ที่สอง: 32 ไบต์ถัดไป
const bodyView = new DataView(buffer, 32, 32);
console.log('Body:', bodyView.byteOffset, bodyView.byteLength); // 32, 32

// เขียน header
headerView.setUint32(0, 0xCAFEBABE);
headerView.setUint32(4, 100); // body length

// อ่าน header จาก bodyView (ต้องคำนวณ offset เอง)
console.log(bodyView.getUint32(-32)); // RangeError! ไม่สามารถอ่านย้อนหลังได้

// วิธีที่ถูกต้อง: ใช้ buffer ตรงๆ หรือ view อื่น
const fullView = new DataView(buffer);
console.log(fullView.getUint32(0)); // 3405691582 (0xCAFEBABE)

ความสัมพันธ์ระหว่าง buffer, byteOffset, byteLength

สำหรับ DataView ใดๆ:

view.byteOffset + view.byteLength <= view.buffer.byteLength

สมการนี้ต้องเป็นจริงเสมอ มิฉะนั้น constructor จะโยน RangeError

กรณีการใช้งานทั่วไป

  • Binary parsing: คำนวณตำแหน่งสำหรับ field ต่างๆ ใน binary format
  • Protocol handling: แยก header/body/payload ใน packet
  • File format parsing: มองเฉพาะ chunk/section ที่สนใจ
  • Memory layout: สร้าง C-style struct layout บน ArrayBuffer
  • Debugging: ตรวจสอบว่า view ตรงตำแหน่งที่คาดหวัง

ตัวอย่าง: Binary Struct Layout

// สมมติโครงสร้าง:
// struct Packet {
//   uint32 magic;     // 0-3
//   uint16 version;   // 4-5
//   uint16 flags;     // 6-7
//   uint32 payloadLen; // 8-11
//   // payload เริ่มที่ offset 12
// }

const buffer = new ArrayBuffer(1024);
const packet = new DataView(buffer);

const HEADER_SIZE = 12;

function parsePacket(buffer) {
  const view = new DataView(buffer);
  
  const magic = view.getUint32(0, false);
  const version = view.getUint16(4, false);
  const flags = view.getUint16(6, false);
  const payloadLen = view.getUint32(8, false);
  
  if (payloadLen > buffer.byteLength - HEADER_SIZE) {
    throw new Error('Invalid payload length');
  }
  
  // สร้าง view สำหรับ payload בלבד
  const payloadView = new DataView(buffer, HEADER_SIZE, payloadLen);
  
  return { magic, version, flags, payloadLen, payloadView };
}

ข้อควรระวัง

  • byteOffset เป็น property ไม่ใช่ method - เรียก ไม่ต้องมีวงเล็บ
  • ค่า byteOffset ถูกกำหนดตอนสร้าง DataView และ ไม่สามารถเปลี่ยนได้
  • ค่า default คือ 0 หากไม่ระบุตอนสร้าง
  • ต้องเป็น multiple ของ element size สำหรับ TypedArray views (แต่ DataView ไม่มีข้อจำกัดนี้)