Edit: odsyłające oto przez Spec wyjaśnienia dr Axel Rauschmayer http://www.2ality.com/2011/06/javascript-equality.html naprawdę wielki napisać.
===
(Ścisła równość): uwzględnia tylko wartości równe temu samemu typowi.
- niezdefiniowany === niezdefiniowany, null === null,
- NaN === nic się w tym,
- Primitive [Number | String | Boolean] === wartość prymitywny równe,
- do siebie (+0 === -0)
- dwa obiekty [Array | Przedmiot | Funkcja] === Tylko samo (dokładnie taki sam podmiot)
==
(Åagodne Równość)
- Jeśli obie wartości mają ten sam typ: porównaj z ===.
- niezdefiniowany == null
- liczba i ciąg: string => liczba i porównać
- logiczną i non-Boolean => non-logiczną do liczby i porównać
- ciąg lub numer => obiekt: konwertować obiekt do prymitywizmu i porównania.
We wszystkich nowoczesnych środowiskach Javascript są one implementowane zupełnie inaczej. W prostych słowach, testy ==
dla podobieństwa poprzez konwersję danych zmiennych na prymitywy (string, number, boolean). ===
testuje ścisłą identyczność, co oznacza dokładnie ten sam obiekt lub prymitywną wartość bez konwersji.
Jeśli nie objOne == objTwo
co faktycznie dzieje [[EQUALS]].call(objOne.valueOf(), objTwo.valueOf())
Rozdzielczość valueOf może być nieco zaangażowane, odbijając się od funkcji narażonych w JS i wewnętrznej rzeczy silnika. Wystarczy powiedzieć, że porównanie zawsze kończy się na dwóch wartościach wymuszonych na prymitywne lub zostanie zgłoszony błąd.
Edytuj:EQUALS
najpierw próbuje STRICT_EQUALS
, co uprzedza resztę procesu.
Interesujące jest to, że valueOf (i jego partner doString) są overridable. Uruchom ten fragment kodu w Chrome (chyba każdy webkit, nie wiem, czy JSC i V8 dzielą tę ciekawość). Będzie to cios mindpiece:
var actions = [];
var overload = {
valueOf: function(){
var caller = arguments.callee.caller;
actions.push({
operation: caller.name,
left: caller.arguments[0] === this ? "unknown" : this,
right: caller.arguments[0]
});
return Object.prototype.toString.call(this);
}
};
overload.toString = overload.valueOf;
overload == 10;
overload === 10;
overload * 10;
10/overload;
overload in window;
-overload;
+overload;
overload < 5;
overload > 5;
[][overload];
overload == overload;
console.log(actions);
wyjściowa:
[ { operation: 'EQUALS',
left: overload,
right: 10 },
{ operation: 'MUL',
left: overload,
right: 10 },
{ operation: 'DIV',
left: 'unknown',
right: overload },
{ operation: 'IN',
left: overload,
right: DOMWindow },
{ operation: 'UNARY_MINUS',
left: overload,
right: undefined },
{ operation: 'TO_NUMBER',
left: overload,
right: undefined },
{ operation: 'COMPARE',
left: overload,
right: 5 },
{ operation: 'COMPARE',
left: 'unknown',
right: overload },
{ operation: 'ToString',
left: 'unknown',
right: overload } ]
Istota różnicy między ==
i ===
ilustrują ===
nie znalazły się na tej liście. Pomija całkowicie podróż do JavascriptLand. Ta przygoda jest kosztowna przy porównywaniu wydajności.
Należy jednak uwzględnić optymalizacje silnika. W przypadku większości obiektów silnik będzie w stanie odciąć większość kroków i pozostać w NativeLand i uzyskać prawie taką samą wydajność. Ale to nie jest gwarancja i jeśli coś uniemożliwia silnikowi korzystanie z optymalizacji, jakąś fantazję w kodzie lub nadpisywanie wbudowanych lub mnóstwo problemów, natychmiast widzisz wynik w wydajności. ===
zmusza go.
===
jest prawie jedyną niezmienną rzeczą w JavaScript.
Nic, co kiedykolwiek zauważysz. Pójść dalej. –
Służą one do różnych celów, a "większa wydajność" nie należy do nich. To nie jest problem, użyj ich, jeśli chcesz uzyskać dostępną funkcjonalność. – meagar
Zalecane uwagi: [Nie wiesz, JS] (https://github.com/getify/You-Dont-Know-JS/blob/master/types%20&%20grammar/ch4.md#loose-equals-vs -strict-equals) –