الذي يساوي المشغل(== vs===) يجب أن يستخدم في مقارنات JavaScript؟




operators equality (20)

JavaScript === vs == .

0==false   // true
0===false  // false, because they are of a different type
1=="1"     // true, auto type coercion
1==="1"    // false, because they are of a different type

أنا أستخدم JSLint للانتقال عبر جافا سكريبت ، وهو يعيد العديد من الاقتراحات ليحل محل == (علامتين idSele_UNVEHtype.value.length == 0 ) مع === (ثلاث علامات متساوية) عند القيام بأشياء مثل مقارنة idSele_UNVEHtype.value.length == 0 داخل if بيان.

هل هناك فائدة من الأداء لاستبدال == مع === ؟

سيتم الترحيب بأي تحسين للأداء حيث يوجد العديد من مشغلي المقارنة.

إذا لم يحدث أي تحويل من نوع ، فهل سيكون هناك زيادة في الأداء على == ؟


باستخدام == المشغل ( المساواة )

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

باستخدام عامل التشغيل === ( الهوية )

true === 1; //false
"2" === 2;  //false

وذلك لأن عامل المساواة == يقوم بكتابة القسر ، وهذا يعني أن المترجم يحاول ضمنيًا تحويل القيم قبل المقارنة.

من ناحية أخرى ، فإن عامل تشغيل الهوية === لا يفعل نوع الإكراه ، وبالتالي لا يقوم بتحويل القيم عند المقارنة.


دعني أضيف هذا المحامي:

إذا كنت في شك ، اقرأ specification !

ECMA-262 هي مواصفات لغة البرمجة النصية التي تعتبر JavaScript بها اللهجة. وبالطبع من الناحية العملية ، من المهم أن تتصرف أكثر المتصفحات أهمية من تعريف مقصور على فئة معينة لكيفية التعامل مع شيء ما. ولكن من المفيد أن نفهم لماذا New String ("a")! == "a" .

اسمحوا لي أن أشرح كيفية قراءة المواصفات لتوضيح هذا السؤال. أرى أنه في هذا الموضوع القديم لا أحد لديه إجابة عن التأثير الغريب جدا. لذا ، إذا كنت تستطيع قراءة المواصفات ، فسوف يساعدك ذلك في مهنتك بشكل هائل. إنها مهارة مكتسبة. لذا ، دعونا نستمر.

البحث في ملف PDF ل === يقودني إلى صفحة 56 من المواصفات: 11.9.4. مشغل متساوٍ متساوٍ (===) ، وبعد الخوض من خلال المواصفات التي أجدها:

11.9.6 خوارزمية المقارنة الصارمة للمساواة
المقارنة x === y ، حيث x و y هي قيم ، تنتج صحيحة أو خاطئة . يتم إجراء مثل هذه المقارنة على النحو التالي:
1. إذا كان النوع (x) مختلفًا عن Type (y) ، فأرجع false .
2. إذا كان النوع (x) غير معرّف ، فأرجع true .
3. إذا كان Type (x) هو Null ، فأرجع true .
4. إذا كان النوع (س) ليس رقم ، انتقل إلى الخطوة 11.
5. إذا كانت x هي NaN ، قم بإرجاع false .
6. إذا كان y هو NaN ، فأرجع كاذباً .
7. إذا كانت x هي نفس قيمة الرقم y ، قم بإرجاع true .
8. إذا كانت x هي +0 و y هي −0 ، فعليك بإرجاع true .
9. إذا كانت قيمة x هي −0 و y هي +0 ، قم بإرجاع true .
10. العودة كاذبة .
11. إذا كانت Type (x) هي String ، فحينئذٍ ترجع true إذا كان x و y هما بالضبط نفس تسلسل الأحرف (نفس الطول والحروف نفسها في المواضع المقابلة) ؛ خلاف ذلك ، تعود كاذبة .
12. إذا كان النوع (x) منطقيًا ، فأرجع true إذا كان x و y كلاهما صحيحين أو كاذبين . خلاف ذلك ، تعود كاذبة .
13. قم بإرجاع true إذا كان x و y يشيران إلى نفس الكائن أو إذا كانا يشيران إلى كائنات مرتبطة ببعضها (انظر 13.1.2). خلاف ذلك ، تعود كاذبة .

المثير للاهتمام هو الخطوة 11. نعم ، تعامل السلاسل على أنها أنواع قيم. ولكن هذا لا يفسر لماذا New String ("a")! == "a" . هل لدينا متصفح غير متوافق مع ECMA-262؟

ليس بهذه السرعة!

دعونا تحقق من أنواع المعاملات. جرب بنفسك عن طريق التفافها في typeof () . أجد أن String ("a") الجديد عبارة عن كائن ، ويتم استخدام الخطوة 1: إرجاع false إذا كانت الأنواع مختلفة.

إذا كنت تتساءل عن سبب عدم إرجاع السلسلة الجديدة ("a") إلى سلسلة ، فما رأيك في بعض التمرينات في قراءة المواصفات؟ إستمتع!

كتب Aidiakapi هذا في تعليق أدناه:

من المواصفات

11.2.2 المشغل الجديد :

إذا كان النوع (منشئ) غير كائن ، فقم برمي استثناء TypeError.

بكلمات أخرى ، إذا لم تكن السلسلة من نوع الكائن ، فلا يمكن استخدامها مع المشغل الجديد.

جديدًا دائمًا ما يعرض كائنًا ، حتى بالنسبة لمُنشئات السلسلة أيضًا. و للأسف! يتم فقدان دلالات القيم للسلاسل (راجع الخطوة 11).

وهذا يعني أخيرا: سلسلة جديدة ("أ")! == "أ" .


في JavaScript ، يعني ذلك نفس القيمة والنوع.

فمثلا،

4 == "4" // will return true

لكن

4 === "4" // will return false 

في الإجابات هنا ، لم أقرأ أي شيء عن الوسائل المتساوية . سيقول البعض أن === تعني المساواة من نفس النوع ، لكن هذا ليس صحيحًا حقًا. يعني في الواقع أن كلا المعاملات تشير إلى نفس الكائن ، أو في حالة أنواع القيم ، لها نفس القيمة .

لذا ، لنأخذ الرمز التالي:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

الشيء نفسه هنا:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

او حتى:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

هذا السلوك ليس دائما واضح. هناك قصة أكثر من كونها متساوية وكونها من نفس النوع.

القاعدة هي:

لأنواع القيم (الأرقام):
إرجاع a === b true إذا كان a و b لهما نفس القيمة وهما من نفس النوع

لأنواع المراجع:
a === b تُرجع true إذا كان a و b يشيران إلى نفس الكائن بالضبط

للسلسلة:
a === b تُرجع true إذا كان a و b كلاهما يحتويان على الأحرف نفسها

السلاسل: الحالة الخاصة ...

السلاسل ليست أنواع قيم ، ولكنها في Javascript تتصرف مثل أنواع القيم ، لذلك ستكون "متساوية" عندما تكون الأحرف في السلسلة متماثلة وعندما تكون من نفس الطول (كما هو موضح في القاعدة الثالثة)

الآن يصبح من المثير للاهتمام:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

لكن ماذا عن هذا؟

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

اعتقدت أن السلاسل تتصرف مثل أنواع القيم؟ حسنًا ، يعتمد الأمر على من تسأل ... في هذه الحالة ، لا يكون a و b من النوع نفسه. a من نوع Object ، في حين أن b من نوع string . فقط تذكر أن إنشاء كائن سلسلة باستخدام مُنشئ String ينشئ شيئًا من نوع Object الذي يتصرف كسلسلة في معظم الأوقات .


في نص عادي ، لن يكون هناك فرق في الأداء. الأهم من ذلك هو حقيقة أن ألف "===" هو 1 كيلوبايت أثقل من ألف "==" :) يمكن لأدوار جافا سكريبت أن تخبرك ما إذا كان هناك اختلاف في الأداء في حالتك.

لكن أنا شخصياً أفعل ما تقترحه JSLint. لا توجد هذه التوصية بسبب مشكلات في الأداء ، ولكن لأن قسرية الكتابة تعني ('\t\r\n' == 0) صحيحة.


مخطط تدفق تنفيذ جافا سكريبت للمساواة / المقارنة "==="

مخطط تدفق تنفيذ جافا سكريبت لعدم المساواة التامة / المقارنة '=='


من غير المحتمل أن يكون هناك أي فرق في الأداء بين العمليتين في الاستخدام الخاص بك. لا يوجد نوع التحويل الذي يجب القيام به لأن كلا المعلمتين من نفس النوع بالفعل. سيكون لكل من العمليات مقارنة نوع متبوعة بمقارنة القيمة.


ويعني المساواة دون إكراه نوع إكراه يعني أن جافا سكريبت لا تقوم تلقائيًا بتحويل أي أنواع بيانات أخرى إلى أنواع بيانات السلسلة

0==false   // true,although they are different types

0===false  // false,as they are different types

2=='2'    //true,different types,one is string and another is integer but 
            javaScript convert 2 to string by using == operator 

2==='2'  //false because by using === operator ,javaScript do not convert 
           integer to string 

2===2   //true because both have same value and same types 

يتصرف مشغل الهوية ( === ) بشكل مشابه لمعاملة المساواة ( == ) باستثناء عدم إجراء تحويل النوع ، ويجب أن تكون الأنواع هي نفسها التي يجب اعتبارها متساوية.

المرجع: برنامج جافا سكريبت التعليمي: مشغّلو مقارنة

سيقارن العامل == للمساواة بعد القيام بأي تحويلات من النوع الضروري . لن يقوم عامل التشغيل === بالتحويل ، لذا إذا لم تكن قيمتان من النوع نفسه === فسيتم إرجاع false . كلاهما سريع على قدم المساواة.

لنقتبس من نصوص جافا سكريبت الرائعة لدوغلاس كروكفورد : The Good Parts ،

يحتوي JavaScript على مجموعتين من عوامل المساواة: === و !== ، !== الشريرين == و != . يعمل الجيدون بالطريقة التي تتوقعونها. إذا كان المعاملان من نفس النوع ولهما نفس القيمة ، فإن === true و !== ينتج false . يقوم التوائم الشريرين بالشيء الصحيح عندما تكون المعاملات من نفس النوع ، ولكن إذا كانوا من أنواع مختلفة ، فإنهم يحاولون إكراه القيم. القواعد التي يقومون بها والتي هي معقدة وغير معهود. هذه بعض الحالات المثيرة للاهتمام:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

إن الافتقار إلى العبور أمر ينذر بالخطر. نصيحتي هي عدم استخدام التوائم الشريرة أبداً. بدلا من ذلك ، استخدم دائما === و !== . كل المقارنات التي تظهر للتو تنتج false مع عامل التشغيل === .

تحديث:

تم طرح نقطة جيدة بواسطة @Casebash في التعليقات وإجابةPhillipe Laybaert المتعلقة بأنواع المراجع. لأنواع المراجع == و === تتصرف باستمرار مع بعضها البعض (ما عدا في حالة خاصة).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

الحالة الخاصة هي عندما تقارن حرفيًا بكائن يتم تقييمه بنفس valueOf الحرفية ، نظرًا valueOf toString أو valueOf . على سبيل المثال ، ضع في الاعتبار مقارنة سلسلة حرفية مع كائن سلسلة تم إنشاؤه بواسطة مُنشئ String .

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

هنا يقوم عامل التشغيل == بفحص قيم الكائنين والعودة true ، ولكن === يرى أنهما ليسا من نفس النوع وأنهما false . أيهما الصحيح؟ هذا يعتمد على ما تحاول مقارنته. نصيحتي هي تجاوز السؤال تماما ومجرد عدم استخدام منشئ String لإنشاء كائنات سلسلة.

مرجع
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3


مقارنة المساواة:

المشغل أو العامل ==

يعود صحيح ، عندما يكون كلا المعاملات متساوية. يتم تحويل المعاملات إلى نفس النوع قبل مقارنة.

>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true

المساواة ونوع المقارنة:

المشغل أو العامل ===

إرجاع true إذا كانت كل المعاملات متساوية ومن النوع نفسه. عادةً ما يكون أفضل وأكثر أمانًا إذا قارنت هذه الطريقة ، لأنه لا يوجد تحويلات من نوع وراء الكواليس.

>>> 1 === '1'
false
>>> 1 === 1
true

=== يحدد المشغل القيم وكذلك أنواع المتغيرات للمساواة.

== يفحص المشغل فقط قيمة المتغيرات للمساواة.


لماذا == لا يمكن التنبؤ بها؟

ما الذي تحصل عليه عندما تقارن سلسلة فارغة "" بالرقم صفر 0 ؟

true

صحيح ، وهذا صحيح وفقا ل == سلسلة فارغة ورقم الصفر هي في نفس الوقت.

ولا تنتهي هناك ، وهنا واحد آخر:

'0' == false // true

الامور حقا غريبة مع المصفوفات.

[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true

ثم أغرب مع سلاسل

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

تزداد الأمور سوءا:

متى يساوي لا يساوي؟

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

دعني أقول ذلك مرة أخرى:

(A == B) && (B == C) // true
(A == C) // **FALSE**

وهذه هي فقط الأشياء المجنونة التي تحصل عليها مع الأوليات.

إنه مستوى جديد تمامًا من الجنون عندما تستخدم == مع الكائنات.

في هذه المرحلة ربما تتساءل ...

لماذا يحدث هذا؟

حسنا ، لأنه على عكس "يساوي الثلاثي" ( === ) الذي يتحقق فقط إذا كانت قيمتين هي نفسها.

== يفعل مجموعة كاملة من الأشياء الأخرى .

لديها معالجة خاصة للوظائف ، معالجة خاصة للقيم الخالية ، غير محددة ، السلاسل ، سمها ما شئت.

انها تحصل على أحمق جدا.

في الواقع ، إذا حاولت كتابة وظيفة تقوم بعمل ما == هل سيبدو شيء مثل هذا:

function isEqual(x, y) { // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") {
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") {
            return x === y.toString();
        } else if(typeof y === "string") {
            return x.toString() === y;
        } 
        return false;
    }

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

فماذا يعني هذا؟

يعني == معقدة.

لأن الأمر معقد ، من الصعب معرفة ما سيحدث عند استخدامه.

مما يعني أنه يمكن أن ينتهي بك الأمر مع البق.

لذلك فإن المعنى من القصة هو ...

اجعل حياتك أقل تعقيدًا.

استخدم === بدلا من == .

النهاية.


نعم فعلا! مهم.

===يقوم المشغل في javascript بالتحقق من القيمة بالإضافة إلى الكتابة حيث يقوم ==المشغل بالتحقق من القيمة فقط (يقوم بتحويل النوع إذا لزم الأمر) .

يمكنك اختبارها بسهولة. الصق الكود التالي في ملف HTML وافتحه في المتصفح

<script>

function onPageLoad()
{
    var x = "5";
    var y = 5;
    alert(x === 5);
};

</script>

</head>

<body onload='onPageLoad();'>

سوف تحصل على ' false ' في حالة تأهب. الآن تعديل onPageLoad()طريقة ل alert(x == 5);ستحصل صحيح .


ببساطة

==يعني المقارنة بين المعاملات مع type conversion

و

===يعني المقارنة بين المعاملات دون type conversion

تحويل النوع في javaScript يعني أن javaScript يقوم تلقائيًا بتحويل أي أنواع بيانات أخرى إلى أنواع بيانات السلسلة.

فمثلا:

123=='123'   //will return true, because JS convert integer 123 to string '123'
             //as we used '==' operator 

123==='123' //will return false, because JS do not convert integer 123 to string 
            //'123' as we used '===' operator 

تكمن المشكلة في أنك قد تواجه مشكلة بسهولة لأن جافا سكريبت بها الكثير من التحويلات الضمنية التي تعني ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

والتي سرعان ما تصبح مشكلة. يمكن أخذ أفضل عينة من لماذا التحويل الضمني هو "الشر" من هذه التعليمة البرمجية في MFC / C ++ التي سيتم تجميع بالفعل بسبب تحويل ضمني من CString إلى HANDLE وهو نوع typedef مؤشر ...

CString x;
delete x;

التي من الواضح خلال وقت التشغيل أشياء غير محددة للغاية ...

جوجل للتحويلات الضمنية في C ++ و STL للحصول على بعض الحجج ضدها ...


مثال بسيط هو

2 == '2'  -> true, values are SAME because of type conversion.

2 === '2'  -> false, values are NOT SAME because of no type conversion.

* المشغلون === مقابل == *

1 == true    =>    true
true == true    =>    true
1 === true    =>    false
true === true    =>    true

أعلى 2 إجابات على حد سواء المذكورة == يعني المساواة و === يعني الهوية. لسوء الحظ ، هذه العبارة غير صحيحة.

إذا كانت كل المعاملات من == هي كائنات ، فيتم مقارنتها لمعرفة ما إذا كانت هي نفس الكائن. إذا أشار كلا المعاملين إلى نفس الكائن ، فسيعود عامل التشغيل بالتساوي إلى true. خلاف ذلك ، وهما لا يساوي.

var a = [1, 2, 3];  
var b = [1, 2, 3];  
console.log(a == b)  // false  
console.log(a === b) // false  

في الكود أعلاه ، يحصل كل من == و === على خطأ لأن a و b لا يمثلان نفس الكائنات.

وهذا يعني: إذا كانت كل المعاملات من == هي كائنات ، = = تتصرف مثل === ، والتي تعني أيضًا الهوية. الفرق الأساسي بين هذين المشغلين هو حول تحويل النوع. == لديه تحويل قبل أن يتحقق من المساواة ، ولكن === لا.


كقاعدة عامة ، سأستخدم بشكل عام ===بدلاً من ==( !==وبدلاً من !=).

تم توضيح الأسباب في الإجابات أعلاه ، كما أن دوغلاس كروكفورد واضحًا جدًا ( JavaScript: The Good Parts ).

ومع ذلك ، هناك استثناء واحد : == nullهي طريقة فعالة للتحقق من "القيمة فارغة أو غير محددة":

if( value == null ){
    // value is either null or undefined
}

على سبيل المثال مسج 1.9.1 يستخدم هذا النمط 43 مرات، و مدقق بناء الجملة JSHint حتى يوفر eqnullخيار مريح لهذا السبب.

من دليل نمط jQuery :

يجب استخدام شيكات المساواة الشريفة (===) لصالح ==. الاستثناء الوحيد هو عند التحقق من وجود غير معرفة والقيمة خالية عن طريق خالية.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;






identity-operator