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 ไม่มีข้อจำกัดนี้)