JavaScript karşılaştırmalarında hangi operatör (== vs ===) kullanılmalıdır?


5665

JavaScript üzerinden gitmek için JSLint kullanıyorum ve bir ifade içinde karşılaştırma gibi şeyler yaparken ==(iki eşittir işaretleri) ===(üç eşittir işaretleri) ile değiştirmek için birçok öneri döndürüyor .idSele_UNVEHtype.value.length == 0if

Değiştirilmesi için bir performans yararı var mıdır ==ile ===?

Birçok karşılaştırma operatörü var olduğu için herhangi bir performans artışı memnuniyetle karşılanacaktır.

Herhangi bir tür dönüşümü gerçekleşmezse, performans artışı olur ==mu?


134
Kime aynı konu ile ilgilenebilir === vs ==, ancak PHP'de okuyabilir: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/…
Marco Demaio

257
Her ihtimale karşı herkes 2012 yılında merak ediyorum: ===bir yolu daha hızlı ==. jsperf.com/comparison-of-comparisons
Ry-

25
@minitech yazın dönüştürme yapmaması gerektiği gibi olmalı
Umur Kontacı

19
@minitech, kimsenin kullanarak fark daha hızlı başvurularını yapacak şüphe ===üzerine ==. Aslında, kıyaslama her iki modern tarayıcıda da büyük bir fark göstermiyor. Şahsen, ==gerçekten katı eşitliğe ihtiyaç duymadıkça genellikle her yerde kullanıyorum .
laurent

5
İşte Crockford'un JS The Good Parts konuşmasının ===ve ==operatörlerin konuştuğu bölüm : youtube.com/…
Oynatılmazsa

Yanıtlar:


6485

Katı eşitlik operatörü ( ===), ==tür dönüştürme yapılmadığı sürece soyut eşitlik operatörüne ( ) aynı şekilde davranır ve türlerin eşit kabul edilmesi için aynı olması gerekir.

Referans: Javascript Eğitimi: Karşılaştırma Operatörleri

==Operatör eşitlik karşılaştırır gerekli tip dönüşümleri yaptıktan sonra . ===Operatör olacak değil iki değer değil aynı türüdür eğer öyleyse, dönüşüm yapmak ===basitçe dönecektir false. Her ikisi de eşit derecede hızlı.

Douglas Crockford'un mükemmel JavaScript'i: İyi Parçalar ,

: JavaScript iki eşitlik operatörleri setleri vardır ===ve !==ve onların kötü ikizler ==ve !=. İyi olanlar beklediğiniz gibi çalışır. İki işlenen aynı türdeyse ve aynı değere sahipse, ===üretir trueve !==üretir false. Kötü ikizler, işlenenler aynı tipteyken doğru olanı yaparlar, ancak farklı türdeyse, değerleri zorlamaya çalışırlar. yaptıkları kurallar karmaşık ve unutulmaz. Bunlar ilginç vakalardan bazıları:

'' == '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

Eşitlik Karşılaştırma Tablosu

Geçişsizlik eksikliği endişe vericidir. Benim tavsiyem asla kötü ikizleri kullanmamak. Bunun yerine, her zaman ===ve kullanın !==. Karşılaştırmaların tamamı sadece üretmek gösterildiği falseile ===operatör.


Güncelleme:

İyi bir nokta tarafından yetiştirildim @Casebash yorumlarda ve @Phillipe Laybaert en cevabı ilişkin nesneler. Nesneler için ==ve ===birbirleriyle tutarlı bir şekilde hareket edin (özel bir durum hariç).

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

Özel durum, bir ilkel öğeyi, onun yöntemi toStringveya valueOfyöntemi nedeniyle aynı ilkel öğe olarak değerlendirilen bir nesne ile karşılaştırmanızdır . Örneğin, ilkel bir dizenin Stringyapıcı kullanılarak oluşturulan bir dize nesnesiyle karşılaştırılmasını düşünün .

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

Burada ==operatör iki nesnenin değerlerini kontrol ediyor ve geri dönüyor true, ancak ===aynı tipte olmadıklarını ve geri döndüklerini görüyor false. Hangisi doğru? Bu gerçekten neyi karşılaştırmaya çalıştığınıza bağlıdır. Benim tavsiyem soruyu tamamen atlamak ve sadece Stringdize değişmezlerinden dize nesneleri oluşturmak için yapıcıyı kullanmamanızdır.

Referans
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3


236
Türler aynıysa === daha hızlı değildir. Türler aynı değilse, === daha hızlı olur çünkü dönüşüm yapmaya çalışmaz.
Kertenkele Bill

520
=== hiçbir zaman == 'dan daha yavaş olmaz. Her ikisi de tür denetimi yapar, bu nedenle === == ile karşılaştırıldığında fazladan bir şey yapmaz, ancak tür denetimi aynı olmadığında === daha erken çıkmasına izin verebilir.
Kertenkele Bill

246
Tüm == /! = İle === /! == değiştirilmesi js dosyasının boyutunu artırır, yüklenmesi daha fazla zaman alır. :)
Marco Demaio

92
“... karmaşık ve unutulmaz yaptıkları kurallar ...” Şimdi bu tür ifadeler programlama sırasında kendinizi çok güvende hissettiriyor ...
Johan

47
Crockford'dan: "Geçişsizlik eksikliği endişe vericidir." Yazılım geliştirirseniz ve bir karşılaştırma operatörünün alarmında geçiş eksikliği bulmazsanız veya == ve === veya dosya boyutu / yükleme süresi arasındaki hız karşılaştırması, karşılaştırma operatörünün davranışının geçiş belirleyiciliğine göre aklınızda öncelikli olursa, geri dönüp yeniden başlamanız gerekebilir.
jinglesthula

1144

İşlecin kullanılması ==( Eşitlik )

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

===Operatörü kullanma ( Kimlik )

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

Bunun nedeni eşitlik operatörünün ==baskı yazmasıdır , yani yorumlayıcı karşılaştırma yapmadan önce değerleri dolaylı olarak dönüştürmeye çalışır.

Öte yandan, kimlik operatörü ===tip baskısı yapmaz ve bu nedenle karşılaştırırken değerleri dönüştürmez ve bu nedenle bir adım atladığı için daha hızlıdır ( This JS benchmark testine göre).


9
@Yazılım Maymun: değer türleri için değil (sayı, boolean, ...)
Philippe Leybaert

34
Kimse Javascript Eşitlik Tablosundan bahsetmediği için burada: dorey.github.io/JavaScript-Equality-Table
blaze

6
İlk ifadede, 'true'nun 1'e değil, 1'in true'a dönüştürüldüğünden emin misiniz?
Shadi Namrouti

2
"Eşitlik" ve "kimlik" terimleri nereden geliyor? Standart bu terimleri kullanmaz. Bu çağrıları =="soyut eşitlik" ve aramaları ==="Katı eşitlik". Çağıran Verilen ==bu geçişli olmadığından, IMHO korkunç "eşitlik" her türlü, ama neden kelime oyunu? Yine de "kimlik" ile ilgili daha fazla sorun yaşıyorum; Sanırım bu terim "işe yarıyor" olsa da oldukça yanıltıcı. Ama cidden, kim "kimlik" terimini icat etti? Ben standart arama ve bulamadım.
Ray Toal

1
"Kimlik" çok yanlış bir kelimedir. Kullandığım tüm dillerdeki kimlik karşılaştırmaları aynı nesnede bir tane anlamına gelir , yani iki referans değişkeni yalnızca eşdeğer varlıkları değil , aynı varlığı gösterir.
Inigo

724

==Ve arasındaki eşitlik karşılaştırmasının ilginç bir resimsel gösterimi ===.

Kaynak: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

===JavaScript eşitlik testi için kullanırken , her şey olduğu gibi. Değerlendirilmeden önce hiçbir şey dönüştürülmez.

JS'de === eşitlik değerlendirmesi


var1 == var2

==JavaScript eşitlik testi için kullanırken , bazı korkak dönüşümler gerçekleşir.

JS'de == eşitlik değerlendirmesi

Hikayeden çıkarılacak ders:

Gerçekleşen ===dönüşümleri tam olarak anlamadığınız sürece kullanın ==.


3
@mfeineis == veya! = yerine === veya! == demek istediniz. Yeni kodlayıcıları karıştırmak istemiyorum;)
katalin_2003

2
Üç dengeyi kullanmak benim deneyimimden sorunlara neden olabilir ve tam olarak anlaşılmadıkça kaçınılmalıdır. zamanın% 99 çünkü iki kaç eder çok daha iyi sonuçlar üretir gerçekten yok tipleri eşit olmak istiyorum.
vsync

13
@vsync: Eğer varsa gerçekten türleri eşit olmak istemiyoruz , siz gerektiğini kullanmak üç eşittir !
SNag

7
Tek istisna: güvenle kullanabilirsiniz x == nullkontrol etmek xolduğunu nullya undefined.
Andy

1
@ user648026: Soru vs ile eşitlik karşılaştırması hakkında . Üst ve alt vakalar zaten eşitsiz, ve dönecektir hem ve operatörler. Ayrıca, anahtar kelimeler , , , , sadece bir olguda JS var ve üst ya da karışık durumlarda kullanılamaz. =====false=====truefalseundefinednullInfinity
SNag

609

Buradaki cevaplarda, eşitliğin ne anlama geldiği hakkında hiçbir şey okumadım . Bazıları bunun eşit ve aynı tür=== anlamına geldiğini söyleyecektir , ancak bu gerçekten doğru değil. Aslında her iki işlenenin aynı nesneye başvurduğu veya değer türlerinde aynı değere sahip olduğu anlamına gelir .

Şimdi aşağıdaki kodu alalım:

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

Aynı şey burada:

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

Ya da:

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

Bu davranış her zaman açık değildir. Hikayede eşit ve aynı türden olmaktan daha fazlası var.

Kural:

Değer türleri (sayılar) için:
a === b eğeraynı değeresahipseavebaynı türdeise true değerini döndürür

Referans türleri için:
a === b eğer if değerini veriravebaynı nesneye başvurursa

Dizeler için: veher ikisi de dize
a === biseavebaynı karakterleri içeriyorsatrue değerini döndürür


Teller: özel durum ...

Dizeler değer türleri değildir, ancak Javascript'te değer türleri gibi davranırlar, bu nedenle dizedeki karakterler aynı olduğunda ve aynı uzunlukta olduklarında (üçüncü kuralda açıklandığı gibi) "eşit" olurlar.

Şimdi ilginç hale geliyor:

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

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

Ama buna ne dersin ?:

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

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

Dizelerin değer türleri gibi davrandığını mı düşündüm? Kimin istediğine bağlı ... Bu durumda a ve b aynı tipte değil. atiptedir Objectederken, btiptedir string. Yapıcıyı kullanarak bir dize nesnesi oluşturmanın, çoğu zaman dize gibi davranan bir Stringşey oluşturduğunu unutmayın .Object


6
activa: Açıklığa kavuştum, dizeler sadece değişmez olduklarında eşittir. new String ("abc") === "abc" yanlış (araştırmamıza göre).
Lawrence Dol

3
new Number() == "0". Firefox'ta ayrıca:(function(){}) == "function () {\n}"
Thomas Eding

3
Nedenini açıkladığınız için teşekkür ederim new String("123") !== "123". Farklı tiplerdir. Basit ama kafa karıştırıcı.
styfle

21
Stringnesneler, diğer nesneler gibi dize gibi davranır . new Stringgerçek dizeler yaratmadığından asla kullanılmamalıdır. Gerçek bir dize ve dize değişmezleri ile yapılabilir veya olmadanString bir işlev olarak newString(0); //"0", Real string, not an object
çağrılabilir

6
Ancak ayrıntılı olarak belirttiğiniz durumlarda, "==" operatörü tamamen aynı şekilde davranır.
Yaron Levi

270

Bu öğüdü ekleyeyim:

Şüpheniz varsa, özellikleri okuyun !

ECMA-262, JavaScript'in lehçesi olduğu bir komut dosyası dili için olan teknik özelliktir. Elbette pratikte, en önemli tarayıcıların nasıl davrandığı, bir şeyin nasıl ele alınması gerektiğine dair ezoterik bir tanımdan daha önemlidir. Ancak neden yeni String ("a")! == "a" olduğunu anlamak yararlı olacaktır .

Lütfen bu soruyu açıklığa kavuşturmak için teknik özellikleri nasıl okuyacağımı açıklayayım. Bu çok eski konuda kimsenin çok garip etki için bir cevabı olmadığını görüyorum. Yani, bir şartnameyi okuyabiliyorsanız, bu mesleğinizde size çok yardımcı olacaktır. Kazanılmış bir beceridir. Öyleyse devam edelim.

PDF dosyasında === aranması beni şartnamenin 56. sayfasına getiriyor: 11.9.4. Katı Eşittir Operatörü (===) ve spesifikasyonlar arasında dolaştıktan sonra şunu buluyorum:

11.9.6 Katı Eşitlik Karşılaştırma Algoritması
x ve y değer olan x === y karşılaştırması doğru veya yanlış üretir . Böyle bir karşılaştırma aşağıdaki gibi yapılır:
  1. (x) Tipi (y) tipinden farklıysa false değerini döndürün .
  2. Tip (x) Tanımsızsa true değerini döndürün .
  3. Tür (x) Boş ise, true değerini döndürün .
  4. Tür (x) Sayı değilse, 11. adıma gidin.
  5. x NaN ise false değerini döndürün .
  6. y NaN ise false değerini döndürün .
  7. x, y ile aynı sayı değeriyse, true değerini döndürün .
  8. x +0 ve y −0 ise, true değerini döndürün .
  9. x −0 ve y +0 ise, true değerini döndürün .
  10. Yanlış döndür .
  11. Tür (x) Dize ise, x ve y tam olarak aynı karakter dizisiyse (karşılık gelen konumlarda aynı uzunluk ve aynı karakterler) true değerini döndürün; aksi takdirde false değerini döndürün .
  12. Tür (x) Boole ise, x ve y ikisi de doğru ya da her ikisi de yanlışsa true değerini döndürün ; aksi takdirde false değerini döndürün .   13. Doğru dön
x ve y aynı nesneye atıfta bulunuyorsa ya da birbirine bağlanmış nesnelere atıfta bulunuyorsa (bkz. 13.1.2). Aksi takdirde, false değerini döndürün .

İlginçtir 11. adımdır. Evet, dizeler değer türleri olarak kabul edilir. Ancak bu neden yeni String ("a")! == "a" olduğunu açıklamaz . ECMA-262 ile uyumlu olmayan bir tarayıcımız var mı?

Çok hızlı değil!

İşlenen türlerini kontrol edelim. Bunları typeof () ile sararak kendiniz deneyin . Ben bulmak yeni String ( "a") bir amacı, ve aşama 1 kullanılır: dönüş sahte türleri farklı ise.

Neden yeni String'in ("a") bir string döndürmediğini merak ediyorsanız , bazıları bir spesifikasyonu okumaya ne dersiniz? İyi eğlenceler!


Aidiakapi bunu aşağıdaki bir yorumda yazdı:

Şartnameden

11.2.2 Yeni Operatör :

Tür (yapıcı) Nesne değilse, bir TypeError istisnası atın.

Başka bir deyişle, String Object türünde olmazsa, yeni işleçle birlikte kullanılamaz.

new , String yapıcıları için bile her zaman bir Object döndürür . Ve ne yazık ki! Dizeler için değer semantiği (bkz. Adım 11) kaybolur.

Ve bu son olarak şu anlama gelir: new String ("a")! == "a" .


(X) türünün sonucunun, typeof?
Dfr

@nalply Davranışla ilgili kaygıyı tam olarak anlayamıyorum new String('x'), çünkü vahşi doğada ilkel sarmalayıcı nesnelerini kullanan herhangi bir kod görmedim ve özellikle bu günlerde çok iyi bir neden olduğunu düşünmüyorum. Hiç kodla karşılaştınız mı?
Andy

@Sorun kötü amaçlı veya sadece özensiz üçüncü taraf kodudur, o zaman kimsenin kullanmadığını varsayamazsınız new String().
nalply

Özensiz ise, === nasıl öğreneceğinizdir. Kötü niyetli new String()ise, muhtemelen endişelerinizin en azı olduğunu düşünüyorum . Teorideki endişeyi anlıyorum, ama yine de, gerçek dünyadan örnekleriniz var mı? Bana göre birisinin undefinedbaşka bir değere ayarlayabileceği eski kaygı gibi .
Andy

Bunu nereden bulduğunuzu bilmiyorum, ancak karşılaştırma algoritmanız adım 2'de yanlış oluyor. Bölüm "7.2.15 Katı Eşitlik Karşılaştırması" önce türlerin aynı olup olmadığını, eğer evet ise Sayı olup olmadığını kontrol eder. Değilse, "7.2.12 SameValueNonNumber (x, y)" bölümü kullanılır.
Rusty Core

101

PHP ve JavaScript'te katı bir eşitlik operatörüdür. Bu, hem türü hem de değerleri karşılaştıracağı anlamına gelir.


10
@David: doğru. Bu yüzden bu cevap yanlış (hatta yanlış)
Philippe Leybaert

7
@David var a = {}, b = {}; a == byanlış döndürür.
nyuszika7h

6
Evet: Aynı tür ve değere sahip iki farklı nesne yanlış karşılaştırır, yani bu cevap yanlıştır. Neden 50 oy var?
alexis

4
Örnekte çünkü bu eski olduğunun farkındayım, ama bu bir çözüm hala "doğru" neden netleştirmek için var a = {}, b = {};hem iken ave bgerçekten bir nesne hem olmakla değiller aynı Teknik olarak değer. Bunlar farklı örneklerdir. Örnekleri karşılaştırmanın ilkelleri karşılaştırmaktan farklı davrandığını unutmayın. Hangi muhtemelen bu karışıklığa ekler. İlkel veri türlerinin örnek sürümünü kullanıyorsanız benzer karşılaştırma davranışı görürsünüz. Örneğin new String('asdf')veya new Number(5). Örn: new Number(5) == new Number(5)aynı değere sahip olmalarına rağmen yanlıştır.
Norman Breau

1
Hepimiz, bir nesneye yapılan başvurunun bir bellek yuvasının göstergesi olduğu için aslında bir Değer Türü olduğunu unutuyoruz. Nesne karşılaştırması, "nesnenin değerini" karşılaştırmaz, ancak her iki işaretçinin de aynı olup olmadığı anlamına gelir; bu, aynı bellek yuvasına başvurdukları anlamına gelir. "===" operatörünün "tür, değer ve bellekteki nesneye yapılan başvurular aynı ise" gerçekten söylemesi gerektiğinden, bu, Türlerin karşılaştırılmasında çok küçük bir farktır.
Stokely

101

Firefox'ta Firebug ile bu kodu kullanarak test ettim :

console.time("testEquality");
var n = 0;
while(true) {
    n++;
    if(n==100000) 
        break;
}
console.timeEnd("testEquality");

ve

console.time("testTypeEquality");
var n = 0;
while(true) {
    n++;
    if(n===100000) 
        break;
}
console.timeEnd("testTypeEquality");

Sonuçlarım (her biri beş kez test edildi ve ortalaması alındı):

==: 115.2
===: 114.4

Bu yüzden minik farkın (bu 100000 yinelemenin üzerinde olduğunu hatırlayın) önemsiz olduğunu söyleyebilirim. Performans yapmak için bir neden değildir=== . Güvenlik yazın (iyi, JavaScript'e gireceğiniz kadar güvenli) ve kod kalitesi.


3
Tip güvenliğinden daha fazla mantıklı doğruluk istiyorsunuz - bazen ==anlaşamadığınızda bir şeyin doğru olmasını istersiniz .
rpjohnst

4
Şimdi, ==operatör için gerçek bir tür tutarlılık olduğunda bunlar nasıl karşılaştırılır ? Unutmayın, o zaman performans artışı olur.
Hubert OG

2
Yukarıda belirtilen daha hızlı nedenlerle sadece tip eşitsizliğini kontrol etmek için uygun şekilde test edildiğinde BÜYÜK fark. jsfiddle.net/4jhuxkb2
Doug Morrow

Böyle bir şeyin performansını işlem / saniye olarak ölçersiniz, tek bir tarayıcıda (yaklaşık% 5 pazar payı olan) tek bir test değil, tip zorlaması (tüm neden) olmayan bir test kullanırken daha yavaştır). Bu tamamen anlamsız bir test. Sen performans kullanmak için sebep olmadığını doğru ===üzerinde ==ama onların performans esasen eşit olduğunu yanlış ve bu testi kanıtlıyor düşünürdüm, diğer birçok kişi kabul etti ve bu, bana tamamen saçma.
Stephen M Irving

97

JavaScript'te aynı değer ve tür anlamına gelir.

Örneğin,

4 == "4" // will return true

fakat

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

87

=== operatör, sıkı bir karşılaştırma operatörü denir gelmez farklılık == operatörü.

2 var a ve b'yi alalım.

İçin "bir == b" olmak gerçek a ve b ihtiyacına değerlendirmek aynı değeri .

"A === b" durumunda, a ve b , doğru olarak değerlendirilebilmesi için aynı değer ve aynı türde olmalıdır .

Aşağıdaki örneği alın

var a = 1;
var b = "1";

if (a == b) //evaluates to true as a and b are both 1
{
    alert("a == b");
}

if (a === b) //evaluates to false as a is not the same type as b
{
    alert("a === b");
}

Özetle ; == operatörünün kullanılması, istemediğiniz durumlarda true olarak değerlendirilebilir; bu nedenle === operatörünün kullanılması daha güvenli olur.

% 90 kullanım senaryosunda hangisini kullandığınız önemli değildir, ancak bir gün beklenmedik davranışlar elde ettiğinizde farkı bilmek faydalıdır.


82

Neden ==bu kadar tahmin edilemez?

Boş bir dizeyi ""sıfır sayısıyla karşılaştırdığınızda ne elde edersiniz 0?

true

Evet, ==boş bir dizeye göre doğru ve sıfır sayısı aynı.

Ve burada bitmiyor, işte bir tane daha:

'0' == false // true

Dizilerle işler gerçekten tuhaflaşıyor.

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

Sonra dizeleri ile garip

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

Daha da kötüye gidiyor:

Ne zaman eşit değil eşittir?

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!

Tekrar söyleyeyim:

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

Ve bu sadece ilkellerle elde ettiğiniz çılgınca şeyler.

==Nesnelerle kullandığınızda yepyeni bir deli seviyesi .

Bu noktada muhtemelen merak ediyorsun ...

Bu neden oluyor?

Çünkü ===iki değerin aynı olup olmadığını kontrol eden "üçlü eşittir" ( ) 'in aksine .

==bir sürü başka şey yapar .

Fonksiyonlar için özel kullanım, null'lar için özel kullanım, tanımsız, dizeler, adını siz koyun.

Oldukça tuhaflaşıyor.

Aslında, ne yapan bir işlev yazmaya çalışırsanız ==, bunun gibi görünecektir:

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();
}

Peki bu ne anlama geliyor?

==Karmaşık olduğu anlamına gelir .

Karmaşık olduğundan, kullandığınızda ne olacağını bilmek zor.

Bu, böceklerle sonuçlanabileceğiniz anlamına gelir.

Yani hikayenin ahlaki ...

Hayatınızı daha az karmaşık hale getirin.

Yerine ===kullanın ==.

Son.


Sizin looseEqualyanlış. Function == Function.toString()doğru, ama looseEqual(Function, Function.toString())yanlış. Başlangıçtaki işlevleri neden filtrelediğinizden emin değilim.
Oriol

@Oriol haklıydı, bunu hesaplamak için kodu güncelledim, FYI testlerime dayanarak "fonksiyonlar" için filtreyi kaldırmak için yeterli değildi, bunun yerine "fonksiyonlar" tamamen ele alınmak zorunda kaldı.
Luis Perez

Unutmayın Spec farklı muamele işlevleri yapar değil, sadece nesneleri vardır. Sorun typeof x === "object", bunun bir nesne olup olmadığını kontrol etmeye güvendiğiniz görülüyor , ancak `typeof sadece null olmayan ilkel öğeler için çalışıyor. Bir değerin bir nesne olup olmadığını kontrol etmenin uygun yolları
Oriol

Fonksiyonları ve nesneleri aynı şekilde tedavi etmeyi denedim ama sonuçların yanlış olduğunu gördüm. Örneğin, işlevler nesneler gibi ele alınırsa, bir işlevi işlevle eşleşen valueOf () veya toString () işlevini uygulayan bir nesneyle karşılaştırmak geçecektir, ancak gerçekte geçmez. Örnek: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- tüm testleri yapan bu JS Fiddle'a bir göz atın : jsfiddle.net/luisperezphd/7k6gcn6g (1.225 test permütasyonu var)
Luis Perez

1
Haklısın, harika gözlemler, bu ==, sonuçları tahmin etmeyi çok zorlaştıran bir çok şeyi yapan ana noktayı vurgularken ===, çok daha basit ve öngörülebilir olan ana nedenlerden ===biri önerilen seçimdir. (Açıkladığınız yanıta bir not ekleyeceğim)
Luis Perez

81

===kontroller, aynı taraf eşittir tip olarak değer .


Misal:

'1' === 1 // will return "false" because `string` is not a `number`

Ortak örnek:

0 == ''  // will be "true", but it's very common to want this check to be "false"

Başka bir yaygın örnek:

null == undefined // returns "true", but in most cases a distinction is necessary

Çoğu zaman bir türsüz bir değer olduğundan eğer umurumda değil, çünkü onay kullanışlı olacağını undefined, null, 0 veya""


7
ayrıca,'string' !== 'number'
Homer

71

Katı eşitlik için Javascript yürütme akış diyagramı / Karşılaştırma '==='

Javascript katı eşitliği

Katı olmayan eşitlik / karşılaştırma için Javascript yürütme akış diyagramı '=='

Javascript eşitliği


stringOkun neden büyük gri kutuyu işaret ettiğini anlamıyorum , kesicinin dizeyi bir sayıya döktüğü anlamına mı geliyor?
vsync

@vsync Gri kutu içindeki dize seçeneğini işaret eder, yani dize -> # || NaN. Javascript bir tür-script dili değildir, yani herhangi bir değişkene sahip olabilir. Yani, o gri kutuyu işaret ediyor.
Samar Panda

Ben sadece stringbir tür ile karşılaştırılması gerekiyordu çünkü bu nedenle döküm amaçlı olup olmadığını sordu number, böylece kesen dize ile karşılaştırılması ve buna göre dize döküm ne bakar?
vsync

1
Büyük gri kutu, ToNumberfarklı türler verildiğinde dönecek olan şeydir , bu nedenle bir dize verilirse yalnızca son seçeneği seçer (ve bir sayıya dönüştürür). ==kullanımları ToNumberdurumlarda sadece string == numberveya boolean == anything(ve sadece yukarıda string/ ' boolean). Bu araçlar ==dönüştürmek asla undefinedya nullda gri kutuya olsa bile. (İster herhangi bir kombinasyonu için undefinedya nullya da her ikisi, ==her zaman dönecektir true., Bir değer önemli değil sol veya sağ tarafında olup olmadığını, aynı zamanda ==(ve ===aynı sonucu dönecektir).)
user2033427

55

JavaScript === ve == .

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

54

Bu, tip zorlama olmadan eşitlik anlamına gelir Zorlama, JavaScript'in başka herhangi bir veri türünü otomatik olarak dize veri türlerine dönüştürmediği anlamına gelir

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 

48

Tipik bir komut dosyasında performans farkı olmayacaktır. Daha da önemlisi bin "===" binden 1 KB daha ağır "==" :) JavaScript profillerinin durumunuzda bir performans farkı olup olmadığını söyleyebilir.

Ama şahsen ben JSLint'in önerilerini yapardım. Bu öneri performans sorunları nedeniyle değil, tip zorlama araçlarının ('\t\r\n' == 0)doğru olması nedeniyle vardır .


4
Her zaman doğru değil. Gzip sıkıştırması ile fark neredeyse göz ardı edilebilir olacaktır.
Daniel X Moore

1
Kabul ediyorum, ama bin "===" aynı zamanda 10 bin kod satırı anlamına gelir yani 1kb daha fazla veya daha az ...;)
Jonny

f bu boyutu hakkında endişe sonra sadece === ile tüm takas, sonra geri av geçmek için av eval sarılmış bir regexp kullanın

46

Eşit karşılaştırma operatörü == kafa karıştırıcıdır ve bundan kaçınılmalıdır.

Eğer varsa ZORUNDA onunla yaşamak, sonra aşağıdaki 3 şeyleri hatırlamak:

  1. Bu geçişli değildir: (a == b) ve (b == C) yol açmaz , (a == C)
  2. Karşılıklı olarak olumsuzlamasına ayrıcalıklıdır: (a == b) ve (a! = B) her zaman a ve b ile birlikte Boole değerlerinin tersidir.
  3. Şüphe durumunda, aşağıdaki doğruluk tablosunu ezberden öğrenin:

JAVASCRIPT'DE EŞİT OPERATÖR GERÇEK TABLOSU

  • Tablodaki her satır 3 karşılıklı "eşit" değerden oluşan bir kümedir, yani aralarındaki 2 değer eşit == işaretini kullanarak eşittir *

** STRANGE: ilk sütundaki herhangi iki değerin bu anlamda eşit olmadığını unutmayın. **

''       == 0 == false   // Any two values among these 3 ones are equal with the == operator
'0'      == 0 == false   // Also a set of 3 equal values, note that only 0 and false are repeated
'\t'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

null == undefined  // These two "default" values are not-equal to any of the listed values above
NaN                // NaN is not equal to any thing, even to itself.

39

Kullanımınızdaki iki işlem arasında herhangi bir performans farkı olması olası değildir. Her iki parametre zaten aynı tür olduğundan, yapılacak bir tür dönüştürme yoktur. Her iki işlem de bir tür karşılaştırması ve ardından bir değer karşılaştırması içerir.


38

Evet! Farkeder.

===javascript'teki işleç, değerin yanı sıra türü== denetler ; burada işleç yalnızca değeri denetler (gerekirse tür dönüşümü yapar) .

resim açıklamasını buraya girin

Kolayca test edebilirsiniz. Aşağıdaki kodu bir HTML dosyasına yapıştırın ve tarayıcıda açın

<script>

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

</script>

</head>

<body onload='onPageLoad();'>

Uyarıda ' yanlış ' alacaksınız . Şimdi size doğru olan onPageLoad()yöntemi değiştirin .alert(x == 5);


33

=== operatör eşitlik için değerlerin yanı sıra değişken türlerini de kontrol eder.

== operatör değişkenlerin değerini eşitlik açısından kontrol eder.


32

Sıkı bir kontrol testi.

Özellikle 0 ile false ve null arasında kontrol ediyorsanız iyi bir şeydir.

Örneğin, aşağıdakilere sahipseniz:

$a = 0;

Sonra:

$a==0; 
$a==NULL;
$a==false;

Tümü geri döner ve bunu istemeyebilirsiniz. Diyelim ki bir dizinin 0. dizinini veya hata durumunda false değerini döndüren bir fonksiyonunuz var. "==" false ile kontrol ederseniz, kafa karıştırıcı bir sonuç elde edebilirsiniz.

Yani yukarıdakiyle aynı şeyle, ancak sıkı bir testle:

$a = 0;

$a===0; // returns true
$a===NULL; // returns false
$a===false; // returns false

3
JavaScript'te bu tamamen yanlıştır ve yanlış şekilde tamamlanmamıştır. 0 != null. -1
Ry-

31

JSLint bazen bir şeyleri değiştirmek için gerçekçi olmayan nedenler verir. türlerin zaten ===aynı olmasıyla aynı performansa sahiptir ==.

Yalnızca türler aynı olmadığında daha hızlıdır, bu durumda türleri dönüştürmeye çalışmaz, ancak doğrudan yanlış döndürür.

Bu nedenle, IMHO, JSLint yeni kod yazmak için kullanılabilir, ancak gereksiz maliyetlerden kaçınmak her ne pahasına olursa olsun kaçınılmalıdır.

Yani, bir çekte sadece bir String olabileceği gerçeğini bildiğiniz gibi bir kontrolde değiştirmek ==için hiçbir neden yoktur .===if (a == 'test')

Kodun bu şekilde değiştirilmesi, geliştiricilerin ve gözden geçirenlerin zamanını boşa harcar ve hiçbir şey başaramaz.


30

basitçe

==ile işlenenler arasındaki karşılaştırma anlamına gelir type conversion

&

===olmayan işlenenler arasında karşılaştırma anlamına gelir type conversion

JavaScript'te tür dönüşümü, javaScript'in diğer veri türlerini otomatik olarak dize veri türlerine dönüştürmesi anlamına gelir.

Örneğin:

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 

26

Basit bir örnek

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

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

25

İlk iki cevap == eşitlik ve === kimlik demektir. Ne yazık ki, bu ifade yanlış.

== ifadesinin her iki işleneni de nesne ise, aynı nesne olup olmadıklarını görmek için karşılaştırılırlar. Her iki işlenen de aynı nesneyi gösteriyorsa, eşit işleç true değerini döndürür. Aksi takdirde, ikisi eşit değildir.

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

Yukarıdaki kodda, hem == hem de === yanlış olur çünkü a ve b aynı nesneler değildir.

Yani: == 'ın her iki işleneni de nesne ise, == === ile aynı şekilde davranır, bu da kimlik anlamına gelir. Bu iki operatörün temel farkı tip dönüşümüdür. == eşitliği kontrol etmeden önce dönüşüm gerçekleştirir, ancak === dönüşüm gerçekleştirmez.


24

Genel bir kural olarak, genellikle kullanmak istiyorsunuz ===yerine ==(ve !==yerine !=).

Nedenleri yukarıdaki cevaplarda açıklanmıştır ve ayrıca Douglas Crockford bu konuda oldukça açıktır ( JavaScript: İyi Parçalar ).

Ancak tek bir istisna vardır : == null'boş veya tanımsız' olup olmadığını kontrol etmenin etkili bir yoludur:

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

Örnek jQuery için 1.9.1 kullanan bu düzeninin 43 kez, ve JSHint sözdizimi denetleyicisi bile sağlar eqnullbu nedenle rahatlatıcı seçeneği.

Gönderen jQuery stil kılavuzu :

== lehine katı eşitlik kontrolleri (===) kullanılmalıdır. Tek istisna, null yoluyla tanımsız ve null olup olmadığının kontrol edilmesidir.

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

22

Sorun, JavaScript'in çok fazla örtük dönüşümü olduğu için kolayca sorun yaşayabileceğiniz ...

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

Yakında bir sorun haline gelir. Örtülü dönüşümün neden "kötülük" olduğuna dair en iyi örnek, aslında bir işaretçi typedef türü olan CString'den HANDLE'a örtük bir dönüşüm nedeniyle derlenecek olan MFC / C ++ 'da bu koddan alınabilir ...

CString x;
delete x;

Açıkçası çalışma zamanı sırasında çok tanımsız şeyler yapıyor ...

Google, C ++ ve STL'deki örtük dönüşümler için ona karşı bazı argümanları almak için ...


2
0 == nullyanlış.
Garrett


21

Eşitlik karşılaştırması:

Şebeke ==

Her iki işlenen de eşit olduğunda true değerini döndürür. İşlenenler karşılaştırılmadan önce aynı türe dönüştürülür.

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

Eşitlik ve tür karşılaştırması:

Şebeke ===

Her iki işlenen de eşit ve aynı türdeyse true değerini döndürür. Bu şekilde karşılaştırırsanız genellikle daha iyi ve daha güvenlidir, çünkü sahne arkası türü dönüşümleri yoktur.

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


20

null ve undefined hiçliktir, yani,

var a;
var b = null;

Burada ave bdeğerleri yok. Oysa, 0, false ve '' değerlerin tümüdür. Tüm bunlar arasında ortak bir şey, hepsinin yanlış değerler olması, yani hepsinin yanlış koşulları karşılamasıdır .

Böylece, 0, false ve '' birlikte bir alt grup oluşturur. Diğer yandan, ikinci alt gruptan null ve undefined. Aşağıdaki görüntüdeki karşılaştırmaları kontrol edin. null ve undefined eşittir. Diğer üçü birbirine eşittir. Ancak, hepsine JavaScript'te yanlış koşullar olarak davranılır.

Resim açıklamasını buraya girin

Bu, herhangi bir nesne ile aynıdır ({}, diziler, vb. Gibi), boş olmayan dize ve Boolean true, hepsi doğru koşullardır. Ama hepsi eşit değil.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.