تاریخچه typeof null در جاوااسکریپت

حمیدرضا مهدوی پناه · خواندن 2 دقیقه · 426 کلمه · ۱۴۰۰/۲/۱

خروجی ‍‍‍‍typeof null توی جاوااسکریپت برابر میشه با "object" که به نادرستی این معنی رو منتقل میکنه که null یه آبجکت (شیء) هست (در صورتی که نیست. null یه primitive value یا مقدار اولیه هست). این یه باگه و چون کدهای فعلی از کار می‌افتن نمیشه رفعش کرد.

باگ «typeof null» بازمانده‌ی اولین نسخه‌ی جاوااسکریپته. توی اون نسخه، مقادیر در واحدهای ۳۲بیتی ذخیره میشدن که از یه برچسب ۱ الی ۳ بیتی برای تشخیص نوع و از بقیه‌ی بیت‌ها برای ذخیره کردن مقدار اصلی داده استفاده میشد. «برچسب نوع داده» در بیت‌های کم‌ارزش ذخیره میشدن. پنج‌تا از این برچسب‌ها وجود داشت:

  • 000: آبجکت. داده به یه آبجکت اشاره میکنه.
  • 1: عدد صحیح (int). داده یه عدد صحیح علامت‌دار (signed integer) ۳۱‌بیتی هست.
  • 010: عدد double. داده یه مرجع به یه عدد اشعاری double هست.
  • 100: رشته (string). داده یه مرجع به یه رشته هست.
  • 110: بولی (boolean). داده یه بولین هست.

اگه بی‌ارزش‌ترین بیت مقدارش 1 بود، برچسب نوع داده یه بیتی بود و اگه بی‌ارزش‌ترین بیت 0 بود، برچسب نوع داده ۳ بیتی بود، که از دو بیت اضافه‌تر، برای تعیین چهار نوع داده مختلف استفاده میشد.

دو مقدار ویژه هم وجود داشتن:

  • مقدار undefined یا JSVAL_VOID که عدد صحیح 32^2- بود (یه عدد خارج از محدوده‌ی اعداد صحیح).
  • مقدار null یا JSVAL_NULL که کد ماشین اشاره‌گر NULL بود: یه نوع داده آبجکت که مقدار اشاره‌گرش 0 بود.

الان دیگه باید واضح باشه که چرا typeof null خروجی آبجکت رو پاسخ میده: چون برچسبِ نوع داده رو چک میکنه و میبینه که برابر با آبجکت هست. کد اولین موتور جاوااسکریپت برای typeof: گام‌هایی که کد بالا طی میکنه:

  • گام (1): موتور بررسی میکنه که آیا مقدار v برابر با undefined یا همون JSVAL_VOID هست یا نه. این بررسی با یه دستور برابر انجام میشه:
1#define JSVAL_IS_VOID(v)  ((v) == JSVAL_VOID)
  • بررسی بعدی (2) اینه که آیا مقدار مورد نظر، برچسب آبجکت داره یا نه. علاوه‌بر این اگه مقدار v قابل صدا‌زدنه یا به عبارتی callable هست (3) یا ویژگی داخلی [[Class]] اون داره میگه که یه تابع هست (4) پس بنابراین v یه تابعه. در غیر این صورت، یه آبجکته.
    این خروجی‌ایه که برای typeof null تولید میشه.
  • بررسی‌های بعدی برای اعداد، رشته‌ها و بولین هست. هیچ بررسی صریحی برای مقدار null وجود نداره، که میتونست خیلی راحت با یه ماکرو C انجام بشه:
1#define JSVAL_IS_NULL(v)  ((v) == JSVAL_NULL)

این باگ شاید خیلی واضح به نظر بیاد، اما نباید فراموش کرد که برای نوشتن اولین نسخه‌ی جاوااسکریپت زمان خیلی کمی در اختیارشون بوده!


منبع: The history of typeof null از وبلاگ 2ality - JavaScript and more