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

ฟังก์ชัน DataView.setInt32() ใน JavaScript

DataView.setInt32() คืออะไร

เมธอด DataView.prototype.setInt32() ใช้สำหรับ เขียนค่าจำนวนเต็มมีเครื่องหมาย 32-bit (signed 32-bit integer) ลงในตำแหน่งที่กำหนดใน DataView ค่าที่เขียนได้จะอยู่ในช่วง -2,147,483,648 ถึง 2,147,483,647 (-2^31 ถึง 2^31-1)

ไวยากรณ์ (Syntax)

dataView.setInt32(byteOffset, value [, littleEndian])
  • byteOffset - ตำแหน่งเริ่มต้นในหน่วยไบต์ (0-indexed)
  • value - ค่าที่จะเขียน (-2147483648 ถึง 2147483647)
  • littleEndian (optional) - true = little-endian, false = big-endian (default: false)

คืนค่า: undefined

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

ตัวอย่างที่ 1: การเขียนและอ่านค่าพื้นฐาน

const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);

view.setInt32(0, 36274722); // big-endian default
console.log(view.getInt32(0)); // 36274722

ตัวอย่างที่ 2: Endianness Handling

const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
const value = 0x12345678; // 305419896

view.setInt32(0, value, false); // big-endian
view.setInt32(4, value, true);  // little-endian

console.log('BE:', view.getInt32(0, false).toString(16)); // 12345678
console.log('LE:', view.getInt32(4, true).toString(16));  // 12345678

ตัวอย่างที่ 3: ค่าลบและ Overflow

const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);

view.setInt32(0, -1);            // 0xFFFFFFFF
view.setInt32(4, -2147483648);   // 0x80000000 (min int32)
view.setInt32(4, 2147483648);    // overflow -> -2147483648

console.log(view.getInt32(0)); // -1
console.log(view.getInt32(4)); // -2147483648

ตัวอย่างที่ 4: การแปลงค่า Float

const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);

view.setInt32(0, 554.36); // truncate -> 554
console.log(view.getInt32(0)); // 554

ตัวอย่างที่ 5: Unix Timestamp Packing

function packTimestamp(date) {
  const buffer = new ArrayBuffer(4);
  const view = new DataView(buffer);
  // Unix timestamp ในวินาที (32-bit signed จะหมดอายุปี 2038)
  const timestamp = Math.floor(date.getTime() / 1000);
  view.setInt32(0, timestamp, false); // big-endian for network
  return buffer;
}

function unpackTimestamp(buffer) {
  const view = new DataView(buffer);
  const timestamp = view.getInt32(0, false);
  return new Date(timestamp * 1000);
}

const now = new Date();
const packed = packTimestamp(now);
console.log(unpackTimestamp(packed).toISOString());

ตัวอย่างที่ 6: อ่านค่าที่ยังไม่ได้ตั้งค่า

const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
console.log(view.getInt32(0)); // 0

Year 2038 Problem (Y2K38)

Signed 32-bit integer สำหรับ Unix timestamp จะล้น (overflow) ในวันที่ 19 มกราคม 2038 03:14:07 UTC (2,147,483,647 วินาทีจาก epoch) หลังจากนั้นค่าจะกลายเป็นลบ (แทนวันที่ในปี 1901)

// ตัวอย่างปัญหา Y2038
const maxInt32 = 2147483647;
const date = new Date(maxInt32 * 1000);
console.log(date.toUTCString()); // Tue, 19 Jan 2038 03:14:07 GMT

// โซลูชัน: ใช้ 64-bit (BigInt64Array) หรือ Float64
const buffer64 = new ArrayBuffer(8);
const view64 = new DataView(buffer64);
view64.setBigInt64(0, BigInt(Date.now()), false); // 64-bit timestamp

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

  • Network protocols: Signed 32-bit fields ใน protocol headers
  • File formats: PNG (chunk lengths สามารถเป็น signed), MP4, ZIP
  • Unix timestamps (legacy): 32-bit time_t (ระวัง Y2038)
  • Database storage: Binary integer serialization
  • Game networking: Entity IDs, coordinates (signed)
  • WebAssembly interop: รับส่ง i32

กรณีพิเศษและข้อผิดพลาด

  • โยน RangeError หาก byteOffset ติดลบ หรือ byteOffset + 4 > byteLength
  • ค่า value จะถูกแปลงด้วย ToInt32 (modulo 2^32 แล้ว interpret เป็น signed)
  • Endianness ต้องตรงกับที่อ่าน (getInt32)
  • สำหรับ timestamp ใหม่ ควรใช้ 64-bit (BigInt64Array หรือ Float64)