Який дорівнює оператору (== vs ===) слід використовувати у порівняннях JavaScript?


5665

Я використовую JSLint для перегляду JavaScript, і він повертає багато пропозицій замінити ==(два знаки рівності) на ===(три знаки рівності), коли виконуються такі речі, як порівняння idSele_UNVEHtype.value.length == 0всередині ifоператора.

Чи є виграш в продуктивності для заміни ==з ===?

Будь-яке підвищення ефективності буде вітатися, оскільки існує багато операторів порівняння.

Якщо не відбудеться перетворення типів, чи не відбудеться підвищення продуктивності ==?


134
Кому це може бути цікаво в цій же темі === vs ==, але в PHP, можна прочитати тут: stackoverflow.com/questions/2401478/why-is-faster-than-in-php / ...
Марко DeMaio

257
Тільки в разі , якщо хто - небудь задавався питанням у 2012 році: ===це спосіб швидше ==. jsperf.com/comparison-of-comparisons
Рибаковим

25
@minitech це має бути так, як це не робить перетворення типів
Umur Kontacı

19
@minitech, я сумніваюся , що хто - то збирається зробити їх застосування значно швидше, використовуючи ===більше ==. Насправді тест не показує великої різниці між обома сучасними браузерами. Особисто я зазвичай користуюся ==скрізь, якщо мені справді не потрібна сувора рівність.
Лоран

5
Ось частина Крокфордського JS The Good Parts розмовляє, де він обговорює ===і ==операторів: youtube.com/… Якщо це не грає, це о 15:20
davidhiggins

Відповіді:


6483

Оператор суворої рівності ( ===) поводиться однаково з абстрактним оператором рівності ( ==), за винятком того, що не проводиться перетворення типів, і типи повинні бути однаковими, щоб вважати рівними.

Довідка: Підручник Javascript: Оператори порівняння

==Оператор порівняння рівності після виконання будь-яких необхідних перетворень типів . ===Оператор НЕ робити перетворення, так що, якщо два значення не одного типу ===буде просто повернутися false. Обидва однаково швидкі.

Цитуючи відмінний JavaScript Дугласа Крокфорда : Хороші частини ,

У 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

Особливий випадок, коли ви порівнюєте примітиву з об'єктом, який оцінює до того самого примітиву, завдяки його 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


236
=== не швидше, якщо типи однакові. Якщо типи не однакові, === буде швидше, оскільки він не намагатиметься зробити перетворення.
Білл Ящірка

520
=== ніколи не буде повільніше, ніж ==. Вони обидва перевіряють тип, тому === не робить нічого зайвого порівняно з ==, але перевірка типу може дозволити === вийти раніше, коли типи не однакові.
Білл Ящірка

246
Заміна всіх == /! = На === /! == збільшує розмір файлу js, для завантаження знадобиться більше часу. :)
Марко Демайо

92
"... правила, за якими вони це роблять, є складними і незабутніми ..." Тепер такі твердження змушують вас почувати себе так безпечно під час програмування ...
Йохан

47
Крокфорд: "Відсутність транзитивності насторожує". Якщо ви розробляєте програмне забезпечення і не виявляєте брак транзитивності в операторі порівняння тривожним, або якщо порівняння швидкості між == та === або розміром / завантаженням файлу має перевагу над транзитивним детермінізмом поведінки оператора порівняння, ви може знадобитися повернутися назад і почати спочатку.
jinglesthula

1144

Використання ==оператора ( рівність )

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

Це тому, що оператор рівності набирає ==примус , тобто інтерпретатор неявно намагається перетворити значення перед порівнянням.

З іншого боку, оператор ідентичності ===не виконує примусу і, отже, не перетворює значення при порівнянні, а тому швидше (як згідно з цим тестом JS-орієнтиру ), коли пропускає один крок.


9
@Software Monkey: не для типів цінності (кількість, булева, ...)
Philippe Leybaert

34
Оскільки ніхто не згадав СТІЛ Javascript Рівності, тут: dorey.github.io/JavaScript-Equality-Table
палахкотять

6
У першому твердженні ви впевнені, що "true" перетворюється на 1, а не 1 перетворюється на true?
Шаді Намроуті

2
Звідки беруться терміни "рівність" та "ідентичність"? Стандарт не використовує ці терміни. Він називає =="абстрактною рівністю" і називає ==="суворою рівністю". Зрозуміло, що називати ==будь-який тип "рівності" - це IMHO жахливо, оскільки воно не є перехідним, але навіщо хитрувати? Хоча я більше займаюся питанням "ідентичності"; Я думаю, що цей термін є досить оманливим, хоча він "працює". Але серйозно, хто придумав термін "ідентичність"? Я шукав стандарт і не зміг його знайти.
Рей Тол

1
"Ідентичність" - це дуже неправильне слово. Порівняння ідентичності в усіх використовуваних мовах означає одне в одному об'єкті , тобто дві опорні змінні вказують не просто на еквівалентні сутності, а на одну і ту ж сутність.
Ініго

724

Цікаве образотворче зображення порівняння рівності між ==та ===.

Джерело: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

При використанні ===для тестування рівності JavaScript все є так, як є. Перед оцінкою нічого не конвертується.

Оцінка рівності === в JS


var1 == var2

При використанні ==для тестування рівності JavaScript відбуваються певні конверсії.

Оцінка рівності == в JS

Мораль історії:

Використовуйте, ===якщо ви повністю не розумієте конверсій, які відбуваються з ==.


3
@mfeineis ви маєте на увазі === або! == замість == або! =. Не хочуть плутати нові кодери;)
katalin_2003

2
з мого досвіду використання трьох рівних може спричинити проблеми і слід уникати, якщо не повністю зрозуміти. дві рівні дають набагато кращі результати, тому що 99% часу я дійсно не хочу, щоб типи були рівними.
vsync

13
@vsync: Якщо ви дійсно не хочете, щоб типи були рівними , вам слід використовувати три рівні !
SNag

7
Єдиний виняток: ви можете безпечно використовувати , x == nullщоб перевірити, xє nullчи undefined.
Енді

1
@ User648026: Йдеться про рівність по порівнянні з ==проти ===. Верхній і нижній регістри все одно нерівні, і вони повернуться falseяк з операторами, так ==і з нижчими ===. Крім того , ключові слова true, false, undefined, null, Infinityіснують в JS тільки в одному випадку, і не можуть бути використані в верхніх або змішаних випадках.
SNag

609

У відповідях тут я нічого не читав про те, що означає рівнозначні . Дехто скаже, що це ===означає рівний і одного типу , але це не зовсім так. Це фактично означає, що обидва операнди посилаються на один і той же об'єкт , або у випадку типів значень мають однакове значення .

Отже, візьмемо наступний код:

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 повертає істинуякщо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яке веде себе як рядок більшу частину часу .


6
activa: Я б уточнив, що рядки такі рівні лише тоді, коли вони є буквальними. new String ("abc") === "abc" є помилковим (згідно мого дослідження).
Лоуренс Дол,

3
new Number() == "0". Також у Firefox:(function(){}) == "function () {\n}"
Томас Едінг

3
Дякую, що пояснили чому new String("123") !== "123". Вони бувають різних типів. Простий, але заплутаний.
стайф

21
Stringоб'єкти поводяться так само, як і будь-який інший об'єкт . new Stringніколи не слід використовувати, оскільки це не створює справжніх рядків. Справжній рядок і може бути виконаний за допомогою рядкових літералів або виклику Stringяк функції без new , наприклад:String(0); //"0", Real string, not an object
Esailija

6
Але у деталях, які ви деталізуєте, оператор "==" поводиться точно так само.
Ярон Леві

270

Дозвольте додати цю пораду:

Якщо ви сумніваєтесь, прочитайте специфікацію !

ECMA-262 - специфікація для мови сценаріїв, якою JavaScript є діалект. Звичайно, на практиці важливо більше, як поводяться найважливіші браузери, ніж езотеричне визначення того, як щось потрібно поводитись. Але корисно зрозуміти, чому новий String ("a")! == "a" .

Дозвольте мені пояснити, як прочитати специфікацію для уточнення цього питання. Я бачу, що в цій дуже старій темі ніхто не мав відповіді за дуже дивний ефект. Тож, якщо ви можете прочитати специфікацію, це допоможе вам у вашій професії надзвичайно. Це набутий навик. Отже, продовжимо.

Пошук у PDF-файлі для === приводить мене до сторінки 56 специфікації: 11.9.4. Оператор строгої рівності (===) , і після проходження через специфікацію я знаходжу:

11.9.6 Алгоритм
порівняння суворої рівності Порівняння x === y, де x і y - значення, дає істинне або хибне . Таке порівняння виконується наступним чином:
  1. Якщо Type (x) відрізняється від Type (y), поверніть false .
  2. Якщо Type (x) не визначено, поверніть true .
  3. Якщо Type (x) - Null, поверніть true .
  4. Якщо Тип (x) не Число, перейдіть до кроку 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. Якщо Type (x) булевий, поверніть true, якщо x і y обидва істинні або обидва помилкові ; в іншому випадку поверніть помилкове .
  13. Повернення правдивеякщо x і y посилаються на один і той же об'єкт або якщо вони посилаються на об'єкти, приєднані один до одного (див. 13.1.2). В іншому випадку поверніть хибне .

Цікавим є крок 11. Так, рядки трактуються як типи значень. Але це не пояснює, чому новий String ("a")! == "a" . Чи є у нас браузер, який не відповідає ECMA-262?

Не так швидко!

Давайте перевіримо типи операндів. Спробуйте самі, загорнувши їх у typeof () . Я вважаю, що новий рядок ("a") є об'єктом, і використовується крок 1: повертайте false, якщо типи різні.

Якщо вам цікаво, чому новий String ("a") не повертає рядок, як щодо певної вправи з читанням специфікації? Веселіться!


Aidiakapi написав це в коментарі нижче:

З специфікації

11.2.2 Новий Оператор :

Якщо Type (конструктор) не є Object, киньте виняток TypeError.

Іншими словами, якщо String не буде типу Object, його не можна було б використовувати з новим оператором.

new завжди повертає Object, навіть для String- конструкторів. І на жаль! Семантика значень для рядків (див. Крок 11) втрачається.

І це, нарешті, означає: новий String ("a")! == "a" .


Результат типу (x) мається на увазі бути таким же, як typeof?
Дфр

@nalply Я точно не розумію занепокоєння щодо поведінки new String('x'), тому що я ніколи не бачив жодного коду в дикій природі, який використовував примітивні предмети обгортки, і я не думаю, що є багато вагомих причин, особливо не в наші дні. Ви коли-небудь стикалися з таким кодом?
Енді

@А коли проблема злісна або просто неохайний сторонній код, то ви не можете припустити, що ніхто не використовує new String().
nalply

Якщо це неохайно, === - це ви дізнаєтесь. Якщо це шкідливо, я думаю, new String()це, мабуть, найменше ваших турбот. Я розумію занепокоєння в теорії, але знову ж таки, чи є у вас реальні приклади? Для мене це як стара тривога, яку хтось міг би встановити undefinedна інше значення.
Енді

Я не знаю, звідки ви це отримали, але ваш алгоритм порівняння помиляється на кроці 2. Розділ "7.2.15 Суворе порівняння рівності" спочатку перевіряє, чи типи однакові, якщо так, чи є вони Числом. Якщо ні, то використовується розділ "7.2.12 SameValueNonNumber (x, y)".
Rusty Core

101

У PHP та JavaScript це суворий оператор рівності. Що означає, вона буде порівнювати і тип, і значення.


10
@David: правильно. Ось чому ця відповідь неточна (або навіть неправильна)
Філіп Лейбаерт

7
@David var a = {}, b = {}; a == bповертає значення false.
nyuszika7h

6
Так: два різні об'єкти з одним типом і значеннями порівнюють помилкові, тобто ця відповідь просто помилкова. Чому він має 50 оновлень?
alexis

4
Я усвідомлюю, що це старе, але уточнити, чому ця відповідь все ще "правильна", це тому, що в прикладі " var a = {}, b = {};Хоча і те, aі bінше" є об'єктом, але технічно вони не мають однакового значення. Вони різні випадки. Зауважте, що порівняння екземплярів поводиться інакше, ніж порівняння примітивів. Що, мабуть, додає цієї плутанини. Ви побачите аналогічну поведінку порівняння, якщо будете використовувати примірні версії примітивних типів даних. Наприклад , new String('asdf')чи new Number(5). Наприклад: new Number(5) == new Number(5)false, навіть якщо вони мають одне значення.
Норман Бро

1
Усі ми забуваємо, що посилання на об’єкт - це фактично Тип значення, оскільки він є вказівником на слот пам'яті. Порівняння об'єктів - це не порівняння "значення об'єкта", а те, чи обидва вказівники однакові, що означало б, що вони посилаються на один і той же слот пам'яті. Це дуже тонка різниця у порівнянні типів, оскільки оператору "===" дійсно потрібно сказати "якщо тип, значення та посилання на об'єкт у пам'яті однакові".
Стоклей

101

Я перевірив це в Firefox з Firebug, використовуючи такий код:

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

і

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

Мої результати (перевірені п'ять разів кожен і в середньому):

==: 115.2
===: 114.4

Тож я б сказав, що різницева різниця (це пам'ятає понад 100000 повторень) незначна. Продуктивність - це не привід для цього ===. Введіть безпеку (ну, настільки ж безпечну, як ви збираєтеся отримати JavaScript), і якість коду.


3
Більше, ніж безпека типу, ви хочете логічної коректності - іноді ви хочете, щоб речі були правдивими, коли ==не погоджуєтесь.
rpjohnst

4
Тепер, як вони порівнюють, коли для ==оператора існує фактичний примус типу ? Пам'ятайте, саме тоді відбувається підвищення продуктивності.
Hubert OG

2
ОСНОВНА різниця при правильному тестуванні з вищезазначених причин швидше перевірити лише нерівність типу. jsfiddle.net/4jhuxkb2
Doug Morrow

Ви вимірюєте ефективність такого подібного в операціях / секунду, а не одиничного тесту в одному браузері (той, який має близько 5% частки ринку), використовуючи console.time (), використовуючи тест, який не приймає примусу типу (вся причина повільніше) до уваги. Це абсолютно безглузде випробування. Ви правильні, що виступ не є причиною для ===надмірного використання, ==але ви помиляєтесь, що їх продуктивність є по суті однаковою і ви вважаєте, що цей тест доводить це, і що багато інших людей погодилися, для мене абсолютно абсурдно.
Стівен М Ірвінг

97

У JavaScript це означає однакове значення та тип.

Наприклад,

4 == "4" // will return true

але

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

87

Оператор === називається оператором суворого порівняння, він дійсно відрізняється від оператора == .

Давайте візьмемо 2 va a і b.

Для "a == b" для оцінки true і a b потрібно мати однакове значення .

У випадку "a === b" a і b повинні бути однаковими, а також однотипними, щоб оцінити їх як істинні.

Візьмемо наступний приклад

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

Підводячи підсумок ; використання оператора == може оцінити справжнє в ситуаціях, коли ви цього не хочете, тому використання оператора === було б безпечнішим.

У сценарії використання 90% не важливо, який саме ви використовуєте, але зручно знати різницю, коли ви отримуєте якусь несподівану поведінку одного дня.


82

Чому ==це так непередбачувано?

Що ви отримуєте, коли порівнюєте порожній рядок ""із числом нуль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();
}

То що це означає?

Це означає == , що складно.

Оскільки це складно, важко зрозуміти, що буде, коли ви його будете використовувати.

Що означає, що у вас можуть виникнути помилки.

Тож мораль історії ...

Зробіть ваше життя менш складним.

Використовуйте ===замість== .

Кінець.


Ви looseEqualпомиляєтесь. Function == Function.toString()правда, але looseEqual(Function, Function.toString())неправда. Не впевнений, чому ви фільтруєте функції на початку.
Оріол

@Oriol ви мали рацію, я оновив код, щоб врахувати це, FYI на основі моїх тестів було недостатньо, щоб видалити фільтр для "функцій", натомість "функції" довелося взагалі по-різному обробляти.
Луїс Перес

Будьте в курсі, що специфікація не розглядає функції по-різному, вони просто об'єкти. Проблема здається, що ви покладаєтесь на те, typeof x === "object"щоб перевірити, чи це об'єкт, але `typeof працює лише для ненульових примітивів. Можливо, вас зацікавить мій список правильних способів перевірити, чи є об’єктом значення
Oriol

Я спробував обробляти функції та об’єкти однаково, але виявив, що результати були невірними. Наприклад, якщо до функцій ставилися як до об'єктів, то порівнюючи функцію з об'єктом, який реалізує функцію valueOf () або toString (), яка відповідає функції, буде передано, але насправді це не так. Приклад: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- перевірити цей JS Скрипка , який запускає всі тести: jsfiddle.net/luisperezphd/7k6gcn6g (там 1225 тест підстановки)
Луїс Перес

1
Ви маєте рацію, чудові спостереження, це підкреслює головний момент, який ==робить багато речей, що ускладнює передбачення результатів, в той час ===як набагато простіший і передбачуваніший, що є однією з головних причин ===- рекомендований вибір. (Я додам записку до відповіді, в якій згадується ваш пункт)
Луїс Перес,

81

===чеки ж сторони рівні по типу , а також вартості .


Приклад:

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

Загальний приклад:

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

Ще один поширений приклад:

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

Багато разів Нетипізовані перевірки буде зручно , тому що ви не дбаєте , якщо значення або undefined, null, 0 або""


7
також,'string' !== 'number'
Гомер

71

Діаграма виконання Javascript для суворої рівності / Порівняння '==='

Сувора рівність Javascript

Діаграма виконання Javascript для не суворої рівності / порівняння '=='

Javascript не рівність


Я не розумію, чому stringстрілка вказує на велику сіру скриньку, це має означати, що переривник кидає рядок до числа?
vsync

@vsync Вказує на параметр рядка в сірому полі, тобто рядок -> # || NaN. Javascript не є мовою скрипту типу, тобто в основному він може мати будь-який тип змінної. Отже, вказується на ту сіру скриньку.
Самар Панда

Я просто запитав, чи це для кастингу, оскільки stringце має бути порівняно з типом number, тож переривник переглядає, з чим слід порівнювати рядок і відповідно передавати рядок?
vsync

1
Велике сіре поле - це те, ToNumberщо повертається, коли даються різні типи, тож якщо йому буде надано рядок, він вибере лише останній варіант (і перетворить його в число). ==використовується ToNumberлише у випадках string == numberабо boolean == anythingвище (і лише в string/ boolean). Це означає, що ==вони ніколи не конвертують undefinedабо nullнавіть якщо вони знаходяться у сірому полі. (Для будь-якої комбінації одного undefinedабо nullобох ==завжди буде повертатися true. Також, значення в лівій чи правій частині не має значення,=====) поверне той самий результат.)
user2033427

55

JavaScript === проти == .

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

Це означає рівність без примусу типу типу примусу означає, що JavaScript не автоматично перетворює будь-які інші типи даних у рядкові типи даних

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

У типовому сценарії різниці в продуктивності не буде. Більш важливим може бути той факт, що тисяча "===" на 1 Кб важчі за тисячу "==" :) профілі JavaScript можуть сказати вам, чи є різниця в продуктивності у вашому випадку.

Але особисто я би зробив те, що пропонує JSLint. Ця рекомендація існує не через проблеми, пов'язані з ефективністю, а тому, що засоби примусу типу ('\t\r\n' == 0)є істинними.


4
Не завжди правда. При компресії gzip різниця була б майже незначною.
Даніель Х Мур

1
Погодьтеся, але тисяча "===" означає також 10 тисяч рядків коду, інакше так 1kb більше чи менше ...;)
Jonny

f, що вас турбує розмір, тоді просто поміняйте всі свої == на ===, а потім скористайтеся

46

Оператор рівного порівняння == заплутаний і його слід уникати.

Якщо ви ПОВИННІ жити з ним, то пам'ятайте наступні 3 речі:

  1. Це не перехідно: (a == b) і (b == c) не призводить до (a == c)
  2. Це взаємно виключає своє заперечення: (a == b) і (a! = B) завжди мають протилежні булеві значення, при цьому всі a і b.
  3. У разі сумнівів, вивчіть напам'ять наступну таблицю істинності:

РІВНІ ТАБЛИЦЯ ПРАВИЛЬНОГО ОПЕРАТОРУ В JAVASCRIPT

  • Кожен рядок у таблиці - це набір із 3 взаємно "рівних" значень, тобто будь-яке 2 значення серед них є рівним, використовуючи знак рівний == *

** СТРАХ: зверніть увагу, що будь-які два значення в першому стовпці не є рівними в цьому сенсі. **

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

Навряд чи буде різниця в продуктивності між двома операціями у вашому використанні. Перетворення типів не повинно бути здійснено, оскільки обидва параметри вже одного типу. Обидві операції матимуть порівняння типів, за яким слід порівняти значення.


38

Так! Це має значення.

===Оператор у javascript перевіряє значення, а також тип, де як ==оператор просто перевіряє значення (робить перетворення типу, якщо потрібно) .

введіть тут опис зображення

Ви можете легко протестувати його. Вставте наступний код у файл HTML і відкрийте його в браузері

<script>

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

</script>

</head>

<body onload='onPageLoad();'>

Ви отримаєте " помилкове " у відповідь. Тепер модифікуйте onPageLoad()метод, щоб alert(x == 5);ви справдилися .


33

=== Оператор перевіряє значення, а також типи змінних на рівність.

== Оператор просто перевіряє значення змінних на рівність.


32

Це суворий тест на перевірку.

Це добре, особливо якщо ви перевіряєте між 0 і false та null.

Наприклад, якщо у вас є:

$a = 0;

Тоді:

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

Все повертається правдою, і цього ви, можливо, не хочете. Припустимо, у вас є функція, яка може повернути 0-й індекс масиву або помилково при відмові. Якщо ви позначите "==" false, ви можете отримати заплутаний результат.

Так що з тим же, що і вище, але суворим тестом:

$a = 0;

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

3
У JavaScript це абсолютно неправильно і неправильно неповно. 0 != null. -1
Ри-

31

JSLint іноді дає нереальні причини змінити речі. ===має точно такі ж показники, як і== якщо типи вже однакові.

Це швидше, лише коли типи неоднакові, і в цьому випадку він не намагається перетворити типи, а безпосередньо повертає помилкові.

Отже, ІМХО, JSLint, можливо, використовуються для написання нового коду, але марної надмірної оптимізації слід уникати будь-якою ціною.

Значить, немає ніяких причин переходити ==на ===чек, якif (a == 'test') коли ви знаєте це на те, що а може бути лише String.

Змінення великого коду таким чином витрачає час розробників та рецензентів і нічого не досягає.


30

Просто

==означає порівняння операндів з 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 

26

Простий приклад - це

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

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

25

У двох кращих відповідях обидва згадані == означає рівність, а === означає ідентичність. На жаль, це твердження є невірним.

Якщо обидва операнди == є об'єктами, то їх порівнюють, щоб побачити, чи є вони однаковими. Якщо обидва операнди вказують на один і той же об'єкт, то рівний оператор повертає істину. Інакше двоє не рівні.

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

У наведеному вище коді обидва == і === стають помилковими, оскільки a і b - не однакові об'єкти.

Це означає: якщо обидва операнди == є об'єктами, == поводиться так само, як ===, що також означає ідентичність. Істотна відмінність цих двох операторів полягає у перетворенні типів. == має перетворення до перевірки рівності, але === не робить.


24

Як правило, я б зазвичай використовував ===замість ==!==замість цього)!= ).

Причини пояснюються у відповідях вище, а також Дуглас Крокфорд досить чітко про це ( JavaScript: хороші частини ).

Однак є один єдиний виняток : == nullце ефективний спосіб перевірити наявність "є недійсним або невизначеним":

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

Наприклад, jQuery 1.9.1 використовує цю схему 43 рази, а перевіряючий синтаксис JSHint навіть надаєeqnull з цієї причини розслабляючий варіант.

З посібника зі стилю jQuery :

Суворі перевірки рівності (===) повинні використовуватися на користь ==. Єдиний виняток - це при перевірці на невизначеність та null шляхом null.

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

22

Проблема полягає в тому, що ви можете легко потрапити в проблеми, оскільки JavaScript має безліч неявних конверсій, що означає ...

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

Що досить скоро стає проблемою. Найкращий зразок того, чому неявна конверсія є "злом", можна взяти з цього коду в MFC / C ++, який насправді буде компілюватися за рахунок неявного перетворення з CString в HANDLE, що є типом вказівника typedef ...

CString x;
delete x;

Що, очевидно, під час виконання робить дуже невизначені речі ...

Google для неявних перетворень на C ++ та STL, щоб отримати деякі аргументи проти цього ...


2
0 == nullнеправдиво.
Гаррет


21

Порівняння рівності:

Оператор ==

Повертає істину, коли обидва операнди рівні. Перед порівнянням операнди перетворюються в один тип.

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

Порівняння рівності та типу:

Оператор ===

Повертає істину, якщо обидва операнди рівні та одного типу. Як правило, краще і безпечніше, якщо ви порівнюєте цей спосіб, оскільки не відбувається позакулісних перетворень.

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

20

Ось зручна таблиця порівняння, яка показує конверсії, які відбуваються, та відмінності між ==та ===.

Як зазначено у висновку:

"Використовуйте три рівні, якщо ви повністю не розумієте конверсій, які відбуваються для двох рівних."

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


20

нульовим і невизначеним є небуття, тобто

var a;
var b = null;

Тут aі bзначення не мають. Тоді як 0, false і '' - всі значення. Одне з них загальне - це те, що всі вони є хибними значеннями, а значить, всі вони відповідають ложним умовам.

Отже, 0, false та '' разом утворюють підгрупу. А з іншого боку, null & undefined утворюють другу підгрупу. Перевірте порівняння на зображенні нижче. нульове та невизначене було б рівним. Інші троє дорівнювали б один одному. Але всі вони трапляються як хибні умови в JavaScript.

Введіть тут опис зображення

Це те саме, що і будь-який об'єкт (наприклад, {}, масиви тощо), не порожній рядок і булева правда - усі умови трибуна. Але, всі вони не рівні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.