مقایسه در جاوااسکریپت – از === تا 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(..) استفاده کرد. برای اشیاء، فقط مقایسهٔ مرجعی انجام می‌شود، نه ساختاری. شناخت این تفاوت‌ها برای نوشتن کدهای دقیق و قابل‌اعتماد ضروری است.


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