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

نوشته رو در وبلاگ یاvar بخونید: yavarjs.ir/posts/typeof-null

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

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

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

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

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

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

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

https://gist.github.com/mahdavipanah/e74e1269660aa23bdf6f57ea74f0de71

گام‌هایی که کد بالا طی میکنه:

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

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

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