مقایسه در جاوااسکریپت – از === تا Object.is و تفاوت مقادیر اولیه و مرجعی

مقایسهٔ مقادیر در جاوااسکریپت یکی از پایه‌های تصمیم‌گیری در برنامه‌هاست. این مقاله به بررسی تفاوت بین مقایسهٔ دقیق (===)، مقایسهٔ ساختاری، و مقایسهٔ هویتی می‌پردازد. همچنین به موارد خاص مانند NaN و -0، و نحوهٔ مقایسهٔ اشیاء و توابع اشاره می‌شود. درک این تفاوت‌ها برای نوشتن کدهای قابل‌اعتماد ضروری است.

مقایسهstrict-equalityObject.isObject.is

~3 دقیقه مطالعه · آخرین به‌روزرسانی ۲۸ مهر ۱۴۰۴

مقدمه


در برنامه‌نویسی، تصمیم‌گیری‌ها معمولاً بر پایهٔ مقایسهٔ مقادیر انجام می‌شوند. جاوااسکریپت چندین روش برای مقایسه ارائه می‌دهد که هرکدام رفتار خاصی دارند. در این مقاله، تفاوت‌های ظریف بین انواع مقایسه‌ها را بررسی می‌کنیم.


مساوی… تقریباً


رایج‌ترین مقایسه در JS بررسی این است که آیا مقدار X با مقدار Y "یکسان" است یا نه. اما "یکسان بودن" در JS همیشه به معنای تطابق دقیق نیست.


عملگر === که به‌عنوان مساوی دقیق (strict equality) شناخته می‌شود، معمولاً هم مقدار و هم نوع را بررسی می‌کند:


3 === 3.0;       // true
"yes" === "yes"; // true
null === null;   // true
42 === "42";     // false
true === 1;      // false
null === undefined; // false

در ظاهر، === نوع و مقدار را بررسی می‌کند و هیچ تبدیل نوعی (coercion) انجام نمی‌دهد. اما این عملگر در دو مورد خاص دروغ می‌گوید: NaN و -0.


مقایسهٔ NaN و -0


NaN === NaN; // false
0 === -0;    // true

برای مقایسهٔ درست NaN از Number.isNaN(..) استفاده کنید، و برای -0 از Object.is(..):


Object.is(NaN, NaN); // true
Object.is(-0, 0);    // false

می‌توان Object.is(..) را به‌عنوان مساوی چهارگانه ==== در نظر گرفت — مقایسه‌ای واقعاً دقیق!


مقایسهٔ اشیاء و توابع


مقایسهٔ اشیاء در JS بر پایهٔ هویت مرجع (reference identity) انجام می‌شود، نه ساختار یا محتوا:


[1, 2, 3] === [1, 2, 3]; // false
{ a: 42 } === { a: 42 }; // false
(x => x * 2) === (x => x * 2); // false

در این مثال‌ها، مقادیر ظاهراً یکسان‌اند، اما چون هرکدام شیء یا تابع جدیدی هستند، مقایسهٔ آن‌ها false می‌شود.


مقایسهٔ مرجعی در عمل


var x = [1, 2, 3];
var y = x;
y === x; // true
y === [1, 2, 3]; // false

در اینجا، y و x به یک آرایهٔ مشترک اشاره دارند، اما مقایسه با آرایهٔ جدید شکست می‌خورد چون مرجع متفاوت است.


مقایسهٔ ساختاری؟ نه در JS!


جاوااسکریپت مکانیزمی برای مقایسهٔ ساختاری اشیاء ندارد. برای چنین مقایسه‌ای باید خودتان منطق بررسی را پیاده‌سازی کنید. اما این کار پیچیده‌تر از آن چیزی‌ست که به نظر می‌رسد — مثلاً مقایسهٔ دو تابع از نظر ساختار یا closure تقریباً غیرممکن است.


جمع‌بندی


در جاوااسکریپت، مقایسهٔ مقادیر به‌ظاهر ساده است، اما در عمل تفاوت‌های ظریفی دارد. === برای بیشتر موارد مناسب است، اما در موارد خاص مانند NaN و -0 باید از Object.is(..) یا Number.isNaN(..) استفاده کرد. برای اشیاء، فقط مقایسهٔ مرجعی انجام می‌شود، نه ساختاری. شناخت این تفاوت‌ها برای نوشتن کدهای دقیق و قابل‌اعتماد ضروری است.


نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

نحوهٔ میزبانی مستقل اپلیکیشن Next.js – پیکربندی، کشینگ، و استراتژی‌های استقرار

nextjs-self-hosting-deployment-cache-isr-proxy-env

ادامه

مقایسه‌های شرطی تبدیل‌پذیر و کلاس‌های پروتوتایپی در جاوااسکریپت – درک دقیق رفتار شرطی و ساختارهای ارث‌بری

این مقاله دو موضوع مهم از ضمیمهٔ A کتاب YDKJSY را بررسی می‌کند: نحوهٔ تبدیل نوع در عبارات شرطی مانند if و while، و الگوی کلاس‌های پروتوتایپی به‌عنوان پیش‌زمینه‌ای برای کلاس‌های ES6. با مثال‌های عملی، تفاوت بین مقایسه‌های دقیق و تبدیل‌پذیر، و نحوهٔ تفویض رفتار از طریق زنجیرهٔ پروتوتایپ روشن می‌شود.

ادامه

در جاوااسکریپت – تفاوت مقدار و مرجع، و فرم‌های متنوع تعریف تابع

در جاوااسکریپت – تفاوت مقدار و مرجع، و فرم‌های متنوع تعریف تابع

ادامه

پروتوتایپ‌ها در جاوااسکریپت – زنجیرهٔ ارجاع، تفویض ویژگی‌ها، و نقش this در رفتار پویا

پروتوتایپ‌ها در جاوااسکریپت مکانیزمی برای ارجاع ویژگی‌ها بین اشیاء هستند. این مقاله به تعریف زنجیرهٔ پروتوتایپ، نحوهٔ تفویض ویژگی‌ها، تفاوت بین دسترسی و انتساب، و نقش کلیدی this در فراخوانی متدهای ارجاع‌شده می‌پردازد. درک این مفاهیم برای طراحی شی‌گرا و رفتارهای پویا در JS ضروری است.

ادامه

Closure و this در جاوااسکریپت – حافظهٔ دامنه و زمینهٔ اجرایی در توابع

Closure و this دو مفهوم بنیادی و گاه گیج‌کننده در جاوااسکریپت هستند. این مقاله به تعریف دقیق closure به‌عنوان حافظهٔ متغیرهای بیرونی در توابع، و بررسی رفتار پویا و وابسته به نحوهٔ فراخوانی در this می‌پردازد. با مثال‌های عملی، تفاوت بین دامنهٔ ثابت و زمینهٔ اجرایی پویا روشن می‌شود.

ادامه

تکرار در جاوااسکریپت – الگوی Iterator، ساختارهای قابل‌تکرار، و مصرف استاندارد داده‌ها

تکرار در جاوااسکریپت – الگوی Iterator، ساختارهای قابل‌تکرار، و مصرف استاندارد داده‌ها

ادامه