สตริงใน JavaScript มีไบต์เท่าไหร่?
ฉันมีสตริง JavaScript ที่มีขนาดประมาณ 500K เมื่อถูกส่งมาจากเซิร์ฟเวอร์ในรูปแบบ UTF-8 ฉันจะบอกขนาดของมันใน JavaScript ได้อย่างไร?
ฉันรู้ว่า JavaScript ใช้ UCS-2 ดังนั้นนั่นหมายถึง 2 ไบต์ต่ออักขระหรือไม่ อย่างไรก็ตาม มันขึ้นอยู่กับการใช้งาน JavaScript หรือไม่? หรือขึ้นอยู่กับการเข้ารหัสหน้าเว็บ หรือบางทีอาจขึ้นอยู่กับประเภทเนื้อหา?
คำตอบ #1
คุณสามารถใช้ Blob เพื่อดูขนาดของสตริงเป็นไบต์ได้
ตัวอย่าง:
console.info(
new Blob(['😂']).size, // 4
new Blob(['👍']).size, // 4
new Blob(['😂👍']).size, // 8
new Blob(['👍😂']).size, // 8
new Blob(['I\'m a string']).size, // 12
// from Premasagar correction of Lauri's answer for
// strings containing lone characters in the surrogate pair range:
// https://stackoverflow.com/a/39488643/6225838
new Blob([String.fromCharCode(55555)]).size, // 3
new Blob([String.fromCharCode(55555, 57000)]).size // 4 (not 6)
);คำตอบ #2
ฟังก์ชันนี้จะคืนขนาดไบต์ของสตริง UTF-8 ใด ๆ ที่คุณส่งให้มัน
function byteCount(s) {
return encodeURI(s).split(/%..|./).length - 1;
}
แหล่งที่มา
เอนจิ้น JavaScript สามารถใช้ UCS-2 หรือ UTF-16 ภายในได้อย่างอิสระ เอนจิ้นส่วนใหญ่ที่ฉันรู้จักใช้ UTF-16 แต่ไม่ว่าจะเลือกแบบใด มันก็เป็นเพียงรายละเอียดของการใช้งานที่ไม่กระทบต่อลักษณะของภาษา
อย่างไรก็ตาม ภาษา ECMAScript/JavaScript เอง จะแสดงตัวอักษรตาม UCS-2 ไม่ใช่ UTF-16
แหล่งที่มา
คำตอบ #3
หากคุณกำลังใช้ node.js มีวิธีง่ายกว่าโดยการใช้บัฟเฟอร์:
function getBinarySize(string) {
return Buffer.byteLength(string, 'utf8');
}
มีไลบรารี npm สำหรับสิ่งนั้น: https://www.npmjs.org/package/utf8-binary-cutter (จากของคุณอย่างซื่อสัตย์)
คำตอบ #4
ค่าของ String ไม่ขึ้นกับการใช้งาน ตามข้อกำหนด ECMA-262 ฉบับที่ 3 แต่ละตัวอักษรแทน หน่วยข้อความ UTF-16 ขนาด 16 บิตเดียว:
4.3.16 ค่าตัวอักษร
ค่าสตริงเป็นสมาชิกของประเภท String และเป็นลำดับที่มีจำนวนจำกัดและมีการจัดเรียงของค่าจำนวนเต็มบวก 16 บิตที่มีจำนวนตั้งแต่ศูนย์ขึ้นไป
หมายเหตุ แม้ว่าค่าทุกค่ามักจะแทนหน่วยข้อความ UTF-16 ขนาด 16 บิตเพียงหน่วยเดียว แต่ภาษานี้ไม่กำหนดข้อจำกัดหรือข้อกำหนดใด ๆ เกี่ยวกับค่าดังกล่าว นอกจากว่าต้องเป็นจำนวนเต็มไม่ติดลบขนาด 16 บิต
คำตอบ #5
นี่คือ 3 วิธีที่ฉันใช้:
TextEncoder
new TextEncoder().encode("myString").length
Blob
new Blob(["myString"]).size
Buffer
Buffer.byteLength("myString", 'utf8')
คำตอบ #6
ลองใช้การผสมนี้โดยใช้ฟังก์ชัน unescape ของ js:
const byteAmount = unescape(encodeURIComponent(yourString)).length
ตัวอย่างกระบวนการเข้ารหัสเต็ม
const s = "1 a ф № @ ®"; // length is 11
const s2 = encodeURIComponent(s); // length is 41
const s3 = unescape(s2); // length is 15 [1-1,a-1,ф-2,№-3,@-1,®-2]
const s4 = escape(s3); // length is 39
const s5 = decodeURIComponent(s4); // length is 11
คำตอบ #7
โปรดทราบว่าหากคุณกำลังมุ่งเป้าไปที่ node.js คุณสามารถใช้ Buffer.from(string).length:
var str = "\u2620"; // => "☠"
str.length; // => 1 (character)
Buffer.from(str).length // => 3 (bytes)
คำตอบ #8
ขนาดของสตริงใน JavaScript คือ
- ก่อน ES6: 2 ไบต์ต่ออักษร
- ES6 และต่อมา: 2 ไบต์ต่ออักขระ หรือ 5 ไบต์ขึ้นไปต่ออักขระ
ก่อน ES6
เสมอ 2 ไบต์ต่ออักขระ UTF-16 ไม่อนุญาตเพราะสเปคบอกว่า "ค่าต้องเป็นจำนวนเต็มบวก 16 บิต" เนื่องจากสตริง UTF-16 อาจใช้ตัวอักขระ 3 หรือ 4 ไบต์ จึงจะละเมิดข้อกำหนด 2 ไบต์ อย่างสำคัญ แม้ว่า UTF-16 จะไม่สามารถสนับสนุนได้อย่างสมบูรณ์ มาตรฐานยังต้องการว่าตัวอักขระ 2 ไบต์ที่ใช้นั้นต้องเป็นตัวอักขระ UTF-16 ที่ถูกต้อง กล่าวอีกนัยหนึ่ง สตริง JavaScript ในยุคก่อน ES6 สนับสนุนชุดย่อยของตัวอักขระ UTF-16
ES6 และหลังจากนั้น
2 ไบต์ต่ออักขระ หรือ 5 ไบต์ขึ้นไปต่ออักขระ ขนาดเพิ่มเติมมีบทบาทเพราะ ES6 (ECMAScript 6) เพิ่มการสนับสนุนการละเว้นจุดโค้ดยูนิโค้ด การใช้ยูนิโค้ด escape ดูได้ดังนี้: \u{1D306}
บันทึกปฏิบัติ
เรื่องนี้ไม่เกี่ยวข้องกับการใช้งานภายในของเครื่องยนต์เฉพาะ ตัวอย่างเช่น เครื่องยนต์บางตัวใช้โครงสร้างข้อมูลและไลบรารีที่รองรับ UTF-16 อย่างเต็มที่ แต่สิ่งที่พวกเขาให้ภายนอกไม่จำเป็นต้องรองรับ UTF-16 อย่างเต็มที่ นอกจากนี้ เครื่องยนต์อาจรองรับ UTF-16 ภายนอกด้วย แต่ไม่ได้บังคับให้ทำ
สำหรับ ES6 กล่าวได้จริง ๆ แล้ว ตัวอักษรจะไม่มีวันยาวเกิน 5 ไบต์ (2 ไบต์สำหรับจุดหนี + 3 ไบต์สำหรับจุดรหัส Unicode) เพราะเวอร์ชันล่าสุดของ Unicode มีตัวอักษรที่เป็นไปได้เพียง 136,755 ตัว ซึ่งใส่เข้าไปใน 3 ไบต์ได้อย่างง่ายดาย อย่างไรก็ตาม เรื่องนี้ไม่ถูกจำกัดโดยมาตรฐานอย่างเคร่งครัด ดังนั้นตามหลักการแล้ว ตัวอักษรเดียวอาจใช้ 4 ไบต์สำหรับจุดรหัสและรวมทั้งหมด 6 ไบต์
ส่วนใหญ่ของตัวอย่างโค้ดที่นี่สำหรับการคำนวณขนาดไบต์ดูเหมือนไม่ได้นำการหนีรหัสจุดโค้ด Unicode ของ ES6 มาคิด ดังนั้นผลลัพธ์อาจไม่ถูกต้องในบางกรณี
