جاوااسکریپت گردی: تبدیل به آرایه
بخش اول جاوااسکریپت گردی رو با عنوان "تبدیل به آرایه" شروع می کنم. مبحثی که توی گروه های مختلف خیلی پرسیده میشه و خیلی بیشتر پاسخ داده میشه!
در این مقاله روش هایی رو معرفی می کنم و از خوبی ها، بدی ها و بعضا از best-practice هاشون هم یادی میکنم.
فرض کنید یک رشته (String) داریم و میخوایم اون رو به تک تک کارکتر هاش در یک آرایه تقسیم کنیم.
روش اول: مثل همیشه کلاسیک!
نکته خاصی تو این روش نیست؛ همون داستان حلقه و ریختن هر حرف در یک آرایه به عنوان خروجی. شاید بپرسید که چرا از prototype استفاده کردیم که باید بگم دلخواهه و میشه به هر شکل دیگه ای نوشت! در حقیقت این روش یک نوع polyfill برای روش دوم هست.
روش دوم: تقسیم بر اساس حروف
این روش بسیار کوتاهه ولی خروجیش دقیقا مشابه روش اول هست!
اما روش اول و دوم (و همینطور ششم) مشکلاتی برای استفاده در برابر کارکتر های non-BMP (non-Basic Multilingual Plane) دارن. کارکتر هایی مثل: ? ? ? ? و تمام شکلک های یونیکد (Unicode Emojies)
مشکل اینجاست که وقتی روی این دسته از کارکتر ها از دو روش بالا استفاده میکنیم، خروجی های عجیب و غریبی میگیریم. برای مثال:
این (ظاهراً) مشکل به این دلیل پیش میاد که دو متد بالا فقط کارکتر هایی که کد 65536 و کمتر دارند رو به صورت طبیعی نشون میدند و برای کارکتر هایی با کد بالاتر، از یک جفت کارکتر از پیش تعیین شده که دارای کد کمتر هستند استفاده می کنند.
خب؛ فهمیدیم مشکل چیه، دلیلش هم مشخص شد؛ برای رفعش چه کنیم؟ روش های پایین جواب سوالتونه!
روش سوم: استفاده از Spread Syntax (ES6)
روش چهارم: استفاده از Array.from (ES6)
روش پنجم: استفاده از RegExp و پرچم u (ES6)
اطلاعات بیشتر درباره پرچم u/:
Stackoverflow - Javascript + Unicode regexes
بعضی از مرورگر ها (مثل مرورگر Microsoft Edge) از پرچم u پشتیبانی نمیکنند که میشه از Regex زیر استفاده کرد:
روش ششم: استفاده از Object.assign (ES6)
روش های 3 تا 6 همه نیازمند محیطی هستند که از ES6 به صورت کامل پشتیبانی میکنه! ولی برای نسخه های پایین تر چه راهی وجود داره؟
روش هفتم: استفاده از Polyfill های ES5
var str = "???";
var stringToArray = function(str) {
var i = 0,
arr = [],
codePoint;
while (!isNaN(codePoint = knownCharCodeAt(str, i))) {
arr.push(String.fromCodePoint(codePoint));
i++;
}
return arr;
}
console.log(stringToArray(str));
// expected output: Array [ "?", "?", "?" ]
البته این Polyfill نیازمند تابع knownCharCodeAt و در بعضی از مرورگر ها String.fromCodePoint هست.
String.fromCodePoint Polyfill:
if (!String.fromCodePoint) {
// ES6 Unicode Shims 0.1 , © 2012 Steven Levithan , MIT License
String.fromCodePoint = function fromCodePoint () {
var chars = [], point, offset, units, i;
for (i = 0; i < arguments.length; ++i) {
point = arguments[i];
offset = point - 0x10000;
units = point > 0xFFFF ? [0xD800 + (offset >> 10), 0xDC00 + (offset & 0x3FF)] : [point];
chars.push(String.fromCharCode.apply(null, units));
}
return chars.join("");
}
}
خب؛ با روش ها آشنا شدیم و حتی Polyfill های جدیدی ایجاد کردیم، ولی همچنان مشکل باقیست...
روش هایی که گفتیم خیلی خوبن؛ ولی در برابر زبان های پیچیده تر و یا شکلک های ترکیبی مثل:Rainbow Flag و... همچنان نتایج عجیبی میدن و در اصلاح دچار miss-interpretation میشن!
برای حل این مشکل هم کتابخانه grapheme-splitter وجود داره که برای هر زبانی از استاندارد خاص خود اون زبان در جداسازی حروف (Split) استفاده میکنه...
در نهایت شمارو دعوت میکنم از این مطلب دیدن کنید تا به یک جمع بندی فوق العاده در این مبحث برسید:
JavaScript has a Unicode problem by Mathias.
مرسی که تا اینجا با من همراه بودید!
مطلبی دیگر از این انتشارات
جاوا اسکریپت رو بلدی ، اما توجه نمیکنی
مطلبی دیگر از این انتشارات
شروع کار با CSS Animation
مطلبی دیگر از این انتشارات
جاوا اسکریپت چه جوری کار میکنه؟ دل و روده ی V8 engine و ۵ تا نکته در مورد کد بهینه نوشتن