diff options
Diffstat (limited to 'files/uk/web/javascript/equality_comparisons_and_sameness/index.html')
-rw-r--r-- | files/uk/web/javascript/equality_comparisons_and_sameness/index.html | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/files/uk/web/javascript/equality_comparisons_and_sameness/index.html b/files/uk/web/javascript/equality_comparisons_and_sameness/index.html new file mode 100644 index 0000000000..67aeef4ef7 --- /dev/null +++ b/files/uk/web/javascript/equality_comparisons_and_sameness/index.html @@ -0,0 +1,495 @@ +--- +title: Перевірка на рівність та однаковість +slug: Web/JavaScript/Equality_comparisons_and_sameness +tags: + - JavaScript + - NaN + - SameValue + - SameValueZero + - Однаковість + - Рівність + - Тотожність + - порівняння +translation_of: Web/JavaScript/Equality_comparisons_and_sameness +original_slug: Web/JavaScript/Перевірка_на_рівність_та_однаковість +--- +<div>{{jsSidebar("Intermediate")}}</div> + +<p>У ES2015 існує чотири алгоритми рівності:</p> + +<ul> + <li>Абстрактна рівність (<code>==</code>);</li> + <li>Строга рівність (<code>===</code>): вживається у методах <code>Array.prototype.indexOf</code>, <code>Array.prototype.lastIndexOf</code> та у блоках <code>case</code>;</li> + <li>SameValueZero (однакове значення або нуль): вживається конструкторами {{jsxref("Global_Objects/TypedArray", "типізованих масивів")}} та {{jsxref("Global_Objects/ArrayBuffer", "ArrayBuffer")}}, так само, як і операціями з {{jsxref("Global_Objects/Map", "Map")}} та {{jsxref("Global_Objects/Set", "Set")}}, а також методами <code>String.prototype.includes</code> та <code>Array.prototype.includes</code>, починаючи з ES2016;</li> + <li>SameValue (однакове значення): вживається у решті випадків.</li> +</ul> + +<p>JavaScript надає три різні операції порівняння значень:</p> + +<ul> + <li><a href="/uk/docs/Web/JavaScript/Reference/Operators/Оператори_порівняння#Ідентичність_строга_рівність_()">===</a> - Строга рівність ("ідентичність", "потрійне дорівнює")</li> + <li><a href="/uk/docs/Web/JavaScript/Reference/Operators/Оператори_порівняння#Рівність_()">==</a> - Абстрактна рівність ("нестрога рівність", "подвійне дорівнює")</li> + <li>метод {{jsxref("Object.is")}} реалізує SameValue (нове у ES2015).</li> +</ul> + +<p>Вибір оператора залежитиме від того, який різновид порівняння вам потрібен. Коротко:</p> + +<ul> + <li>подвійне дорівнює (<code>==</code>) виконає приведення типів при порівнянні двох величин, і оброблятиме <code>NaN</code>, <code>-0</code> та <code>+0</code> особливим чином, у відповідності з IEEE 754 (тому <code>NaN != NaN</code>, а <code>-0 == +0</code>);</li> + <li>потрійне дорівнює (<code>===</code>) виконує таке саме порівняння, як і подвійне дорівнює (і так само поводиться з <code>NaN</code>, <code>-0</code> та <code>+0</code>), але без приведення типів; якщо типи величин відрізняються, повертається <code>false</code>.</li> + <li><code>Object.is</code> не виконує приведення типів та не обробляє <code>NaN</code>, <code>-0</code> та <code>+0</code> особливим чином (має таку саму поведінку, як і <code>===</code>, за винятком цих спеціальних числових значень).</li> +</ul> + +<p>Зауважте, що усі відмінності операторів стосуються їхнього поводження з простими величинами; жоден з них не порівнює, чи є параметри концептуально однаковими за структурою. Для будь-яких не примітивних об'єктів <code>x</code> та <code>y</code>, що мають однакову структуру, але є двома окремими об'єктами, всі вищенаведені форми порівняння вертатимуть <code>false</code>.</p> + +<h2 id="Строга_рівність_за_допомогою">Строга рівність за допомогою <code>===</code></h2> + +<p>Строга рівність перевіряє рівність двох значень. До жодного з них не застосовується неявне приведення перед порівнянням. Якщо значення мають різні типи, вони вважаються нерівними. Якщо значення мають однаковий тип, не є числами, і мають однакові значення, вони вважаються рівними. Нарешті, якщо обидва значення є числами, вони вважаються рівними, якщо обидва не дорівнюють <code>NaN</code> та мають однакові значення, або якщо одне дорівнює <code>+0</code>, а інше <code>-0</code>.</p> + +<pre class="brush: js">var num = 0; +var obj = new String('0'); +var str = '0'; + +console.log(num === num); // true +console.log(obj === obj); // true +console.log(str === str); // true + +console.log(num === obj); // false +console.log(num === str); // false +console.log(obj === str); // false +console.log(null === undefined); // false +console.log(obj === null); // false +console.log(obj === undefined); // false +</pre> + +<p>Строга рівність майже завжди є доречною операцією порівняння. Для усіх значень, крім чисел, вона використовує очевидну семантику: значення дорівнює лише самому собі. Для чисел вона використовує трохи відмінну семантику, щоб згладити два граничні випадки. Перший полягає в тому, що нуль з рухомою комою є або додатним, або від'ємним. Це корисно для представлення деяких математичних рішень, але, оскільки у більшості ситуацій різниця між <code>+0</code> та <code>-0</code> не має значення, строга рівність вважає їх одним значенням. Другий випадок полягає в тому, що рухома кома містить концепцію не числа, <code>NaN</code> (not a number), для вирішення деяких нечітко визначених математичних проблем: наприклад, від'ємна нескінченність, додана до позитивної нескінченності. Строга рівність вважає значення <code>NaN</code> нерівним будь-якій іншій величині, в тому числі самому собі. (Єдиний випадок, у якому <code>(x !== x)</code> дорівнює <code>true</code>, це коли <code>x</code> дорівнює <code>NaN</code>.)</p> + +<h2 id="Нестрога_рівність_за_допомогою">Нестрога рівність за допомогою ==</h2> + +<p>Нестрога рівність порівнює два значення <em>після</em> приведення обох значень до спільного типу. Після приведення (один чи обидва значення можуть зазнати перетворення), фінальне порівняння виконується так само, як його виконує оператор <code>===</code>. Нестрога рівність є <em>симетричною</em>: вираз <code>A == B</code> за семантикою завжди ідентичний <code>B == A</code> для будь-яких значень <code>A</code> та <code>B</code> (за винятком порядку, в якому виконуються перетворення).</p> + +<p>Порівняльна операція виконується наступним чином для операндів різних типів:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="row"></th> + <th colspan="7" scope="col" style="text-align: center;">Операнд B</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row"></th> + <td></td> + <td style="text-align: center;">Undefined</td> + <td style="text-align: center;">Null</td> + <td style="text-align: center;">Number</td> + <td style="text-align: center;">String</td> + <td style="text-align: center;">Boolean</td> + <td style="text-align: center;">Object</td> + </tr> + <tr> + <th colspan="1" rowspan="6" scope="row">Операнд A</th> + <td>Undefined</td> + <td style="text-align: center;"><code>true</code></td> + <td style="text-align: center;"><code>true</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + </tr> + <tr> + <td>Null</td> + <td style="text-align: center;"><code>true</code></td> + <td style="text-align: center;"><code>true</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + </tr> + <tr> + <td>Number</td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>A === B</code></td> + <td style="text-align: center;"><code>A === ToNumber(B)</code></td> + <td style="text-align: center;"><code>A === ToNumber(B)</code></td> + <td style="text-align: center;"><code>A == ToPrimitive(B)</code></td> + </tr> + <tr> + <td>String</td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>ToNumber(A) === B</code></td> + <td style="text-align: center;"><code>A === B</code></td> + <td style="text-align: center;"><code>ToNumber(A) === ToNumber(B)</code></td> + <td style="text-align: center;"><code>A == ToPrimitive(B)</code></td> + </tr> + <tr> + <td>Boolean</td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>ToNumber(A) === B</code></td> + <td style="text-align: center;"><code>ToNumber(A) === ToNumber(B)</code></td> + <td style="text-align: center;"><code>A === B</code></td> + <td style="text-align: center;"><code>ToNumber(A) == ToPrimitive(B)</code></td> + </tr> + <tr> + <td>Object</td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>false</code></td> + <td style="text-align: center;"><code>ToPrimitive(A) == B</code></td> + <td style="text-align: center;"><code>ToPrimitive(A) == B</code></td> + <td style="text-align: center;"><code>ToPrimitive(A) == ToNumber(B)</code></td> + <td style="text-align: center;"><code>A === B</code></td> + </tr> + </tbody> +</table> + +<p>У наведеній вище таблиці <code>ToNumber(A)</code> пробує перетворити свій аргумент на число перед порівнянням. Його поведінка еквівалентна операції <code>+A</code> (унарний оператор +). <code>ToPrimitive(A)</code> пробує перетворити свій аргумент-об'єкт на просту величину, викликаючи в різній послідовності методи <code>A.toString</code> та <code>A.valueOf</code> на операнді <code>A</code>.</p> + +<p>Традиційно, та згідно з ECMAScript, усі об'єкти нестрого нерівні <code>undefined</code> та <code>null</code>. Але більшість переглядачів дозволяють дуже вузькому класу об'єктів (зокрема, об'єкту <code>document.all</code> на будь-якій сторінці) у певному контексті поводитись, як наче вони <em>емулюють</em> значення <code>undefined</code>. Нестрога рівність у такому контексті: <code>null == A</code> та <code>undefined == A</code> оцінить як true тільки за умови, що A є об'єктом, який <em>емулює</em> <code>undefined</code>. У всіх інших випадках об'єкт ніколи не є нестрого рівним <code>undefined</code> або <code>null</code>.</p> + +<pre class="brush: js">var num = 0; +var obj = new String('0'); +var str = '0'; + +console.log(num == num); // true +console.log(obj == obj); // true +console.log(str == str); // true + +console.log(num == obj); // true +console.log(num == str); // true +console.log(obj == str); // true +console.log(null == undefined); // true + +// обидва дорівнюють false, крім виняткових випадків +console.log(obj == null); +console.log(obj == undefined); +</pre> + +<p>Деякі розробники вважають, що краще ніколи не використовувати нестрогу рівність. Результат порівняння за допомогою строгої рівності легше передбачити, а, оскільки жодного приведення типів не виконується, обчислення може відбуватись швидше.</p> + +<h2 id="Порівняння_за_алгоритмом_same-value">Порівняння за алгоритмом same-value</h2> + +<p>Порівняння same-value (однакове значення) спрямоване на останній випадок використання: визначення того, чи є два значення <em>функціонально ідентичними</em> в усіх контекстах. (Цей випадок використання демонструє приклад <a href="https://uk.wikipedia.org/wiki/%D0%9F%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF_%D0%BF%D1%96%D0%B4%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B8_%D0%9B%D1%96%D1%81%D0%BA%D0%BE%D0%B2" title="http://en.wikipedia.org/wiki/Liskov_substitution_principle">принципу підстановки Лісков</a>.) Один приклад виникає, коли робиться спроба змінити незмінну властивість:</p> + +<pre class="brush: js">// Додати незмінну властивість NEGATIVE_ZERO у конструктор Number. +Object.defineProperty(Number, 'NEGATIVE_ZERO', + { value: -0, writable: false, configurable: false, enumerable: false }); + +function attemptMutation(v) { + Object.defineProperty(Number, 'NEGATIVE_ZERO', { value: v }); +} +</pre> + +<p><code>Object.defineProperty</code> викине виняток, коли спроба змінити незмінну властивість дійсно змінить її, але нічого не зробить, якщо не робиться запитів на реальну зміну. Якщо <code>v</code> дорівнює <code>-0</code>, запитів на зміну не виконувалось, жодна помилка не буде викинута. Внутрішньо, коли перевизначається незмінна властивість, нове значення порівнюється з наявним значенням за допомогою алгоритму same-value.</p> + +<p>Алгоритм same-value надається методом {{jsxref("Object.is")}}.</p> + +<h2 id="Порівняння_за_алгоритмом_same-value-zero">Порівняння за алгоритмом same-value-zero</h2> + +<p>Схожий на алгоритм same-value, але вважає +0 та -0 рівними.</p> + +<h2 id="Абстрактна_рівність_строга_рівність_та_однакове_значення_у_специфікації">Абстрактна рівність, строга рівність та однакове значення у специфікації</h2> + +<p>У ES5 порівняння, що виконується за допомогою <a href="/uk/docs/Web/JavaScript/Reference/Operators/Оператори_порівняння#Рівність_()" title="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators"><code>==</code></a>, описане у <a href="http://ecma-international.org/ecma-262/5.1/#sec-11.9.3" title="http://ecma-international.org/ecma-262/5.1/#sec-11.9.3">Розділі 11.9.3, Алгоритм абстрактної рівності</a>. Порівняння <a href="/uk/docs/Web/JavaScript/Reference/Operators/Оператори_порівняння#Ідентичність_строга_рівність_()" title="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators"><code>===</code></a> у <a href="http://ecma-international.org/ecma-262/5.1/#sec-11.9.6" title="http://ecma-international.org/ecma-262/5.1/#sec-11.9.6">11.9.6, Алгоритм строгої рівності</a>. (Сходіть почитайте. Вони короткі та легкі для читання. Підказка: читайте спочатку алгоритм строгої рівності.) ES5 також описує, у <a href="http://ecma-international.org/ecma-262/5.1/#sec-9.12" title="http://ecma-international.org/ecma-262/5.1/#sec-9.12">Розділі 9.12, Алгоритм SameValue</a>, для внутрішнього використання рушієм JS. Він значною мірою такий самий, як алгоритм строгої рівності, за винятком того, як 11.9.6.4 та 9.12.4 відрізняються у поводженні з {{jsxref("Number","числами")}}. ES2015 просто відкриває цей алгоритм через {{jsxref("Object.is")}}.</p> + +<p>Щодо подвійного та потрійного дорівнює, можна побачити, що, за винятком попередньої перевірки типу у 11.9.6.1, алгоритм строгої рівності є підмножиною алгоритму абстрактної рівності, бо 11.9.6.2–7 відповідають 11.9.3.1.a–f.</p> + +<h2 id="Модель_для_розуміння_порівняльних_алгоритмів">Модель для розуміння порівняльних алгоритмів?</h2> + +<p>До ES2015 ви, можливо, сказали б щодо подвійного та потрійного дорівнює, що один є "посиленою" версією іншого. Наприклад, хтось може сказати, що подвійне дорівнює є посиленою версією потрійного дорвінює, тому що перше робить усе, що робить друге, але з приведенням типів у операндах. Наприклад, <code>6 == "6"</code>. (Альтернативно, хтось може сказати, що подвійне дорівнює є основою, а потрійне дорівнює є посиленою версією, тому що воно вимагає, щоб два операнди були однакового типу, і таким чином, вводить додаткове обмеження. Яка модель краща для розуміння, залежить від того, яким чином ви розглядаєте питання.)</p> + +<p>Однак, така модель вбудованих операторів однаковості не може бути поширена на ES2015 з включенням у свій "діапазон" методу {{jsxref("Object.is")}}. Метод {{jsxref("Object.is")}} не просто "абстрактніший", ніж подвійне, або "суворіший", ніж потрійне дорівнює, він також не вписується десь посередині (тобто, будучи одночасно суворішим за подвійне дорівнює, але менш строгим за потрійне дорівнює). Як можна побачити з наведеної нижче порівняльної таблиці, все через поводження {{jsxref("Object.is")}} з {{jsxref("NaN")}}. Зверніть увагу, що, якби значення <code>Object.is(NaN, NaN)</code> дорівнювало <code>false</code>, ми <em>могли б</em> сказати, що метод вписується у абстрактно-суворий діапазон як ще суворіший за потрійне дорівнює, такий, що розрізняє <code>-0</code> та <code>+0</code>. Однак, його поводження з {{jsxref("NaN")}} означає, що це не так. На жаль, {{jsxref("Object.is")}} просто має сприйматись з точки зору його особливих характеристик, а не його абстрактності чи суворості у порівнянні з операторами рівності.</p> + +<table class="standard-table" style="height: 944px; width: 892px;"> + <caption>Порівняльні алгоритми</caption> + <thead> + <tr> + <th scope="col" style="text-align: center;">x</th> + <th scope="col" style="text-align: center;">y</th> + <th scope="col" style="width: 10em; text-align: center;"><code>==</code></th> + <th scope="col" style="width: 10em; text-align: center;"><code>===</code></th> + <th scope="col" style="width: 10em; text-align: center;"><code>Object.is</code></th> + <th scope="col" style="width: 10em; text-align: center;"><code>SameValueZero</code></th> + </tr> + </thead> + <tbody> + <tr> + <td><code>undefined</code></td> + <td><code>undefined</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>null</code></td> + <td><code>null</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>true</code></td> + <td><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>false</code></td> + <td><code>false</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>'foo'</code></td> + <td><code>'foo'</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>0</code></td> + <td><code>0</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>+0</code></td> + <td><code>-0</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>+0</code></td> + <td><code>0</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>-0</code></td> + <td><code>0</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + <tr> + <td><code>0</code></td> + <td><code>false</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>""</code></td> + <td><code>false</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>""</code></td> + <td><code>0</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>'0'</code></td> + <td><code>0</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>'17'</code></td> + <td><code>17</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>[1, 2]</code></td> + <td><code>'1,2'</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>new String('foo')</code></td> + <td><code>'foo'</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>null</code></td> + <td><code>undefined</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>null</code></td> + <td><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>undefined</code></td> + <td><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>{ foo: 'bar' }</code></td> + <td><code>{ foo: 'bar' }</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>new String('foo')</code></td> + <td><code>new String('foo')</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>0</code></td> + <td><code>null</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>0</code></td> + <td><code>NaN</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>'foo'</code></td> + <td><code>NaN</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + </tr> + <tr> + <td><code>NaN</code></td> + <td><code>NaN</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(255, 144, 144); text-align: center;"><code>false</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + <td style="background-color: rgb(144, 255, 144); text-align: center;"><code>true</code></td> + </tr> + </tbody> +</table> + +<h2 id="Коли_використовувати_jsxrefObject.is_та_потрійне_дорівнює">Коли використовувати {{jsxref("Object.is")}} та потрійне дорівнює</h2> + +<p>Загалом, єдиний випадок, коли особлива поведінка {{jsxref("Object.is")}} щодо нулів може становити інтерес, це впровадження певних схем метапрограмування, особливо тих, що стосуються дескрипторів властивостей, коли бажано, щоб ваша робота відображала певні характеристики {{jsxref("Object.defineProperty")}}. Якщо ваш випадок цього не вимагає, пропонується уникати {{jsxref("Object.is")}} та використовувати натомість <a href="/uk/docs/Web/JavaScript/Reference/Operators/Оператори_порівняння#Ідентичність_строга_рівність_()" title="/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators"><code>===</code></a>. Навіть якщо у вашому випадку вимагається, щоб порівняння двох {{jsxref("NaN")}} повертало <code>true</code>, загалом, легше перевіряти {{jsxref("NaN")}} окремо (за допомогою методу {{jsxref("isNaN")}}, доступного у попередніх версіях ECMAScript), ніж розбиратися, як навколишні обчислення можуть вплинути на знаки нулів, які зустрінуться вам у порівняннях.</p> + +<p>Ось невичерпний список вбудованих методів та операцій, що можуть спричинити відмінності між <code>-0</code> та <code>+0</code>, які можуть проявити себе у коді:</p> + +<dl> + <dt><a href="/uk/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Unary_negation"><code>- (унарний мінус)</code></a></dt> +</dl> + +<dl> + <dd> + <pre class="brush:js">let stoppingForce = obj.mass * -obj.velocity;</pre> + + <p>Якщо <code>obj.velocity</code> дорівнює <code>0</code> (або обчислюється як <code>0</code>), в цьому місці отримуємо <code>-0</code>, який переходить далі у <code>stoppingForce</code>.</p> + </dd> +</dl> + +<dl> + <dt>{{jsxref("Math.atan2")}}</dt> + <dt>{{jsxref("Math.ceil")}}</dt> + <dt>{{jsxref("Math.pow")}}</dt> + <dt>{{jsxref("Math.заокругелння","Math.round")}}</dt> +</dl> + +<dl> + <dd>У деяких випадках <code>-0</code> може потрапити у вираз як результат одного з цих методів, навіть коли жоден параметр не дорівнює <code>-0</code>. Наприклад, при використанні {{jsxref("Math.pow")}} для піднесення {{jsxref("Infinity", "-Infinity")}} до будь-якого від'ємного непарного степеня, отримуємо <code>-0</code>. Звертайтесь до документації щодо окремих методів.</dd> +</dl> + +<dl> + <dt>{{jsxref("Math.floor")}}</dt> + <dt>{{jsxref("Math.max")}}</dt> + <dt>{{jsxref("Math.min")}}</dt> + <dt>{{jsxref("Math.sin")}}</dt> + <dt>{{jsxref("Math.sqrt")}}</dt> + <dt>{{jsxref("Math.tan")}}</dt> +</dl> + +<dl> + <dd>Можливо отримати <code>-0</code> як результат виконання даних методів у певних випадках, коли <code>-0</code> присутній як один з параметрів. Наприклад, <code>Math.min(-0, +0)</code> повертає <code>-0</code>. Звертайтесь до документації щодо окремих методів.</dd> +</dl> + +<dl> + <dt><code><a href="/uk/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Побітове_НЕ" title="Побітове НЕ">~</a></code></dt> + <dt><code><a href="/uk/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#<<_Лівий_зсув" title="Лівий зсув"><<</a></code></dt> + <dt><code><a href="/uk/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#>>_Правий_зсув_з_розширенням_знаку" title="Правий зсув з розширенням знаку">>></a></code></dt> + <dd>Кожний з цих операторів внутрішньо використовує алгоритм ToInt32. Оскільки існує лише одне представлення 0 у внутрішньому 32-бітному цілочисельному типі, <code>-0</code> не збережеться після подвійної операції інверсії. Наприклад, і <code>Object.is(~~(-0), -0)</code>, і <code>Object.is(-0 << 2 >> 2, -0)</code> повернуть <code>false</code>.</dd> +</dl> + +<p>Покладатися на метод {{jsxref("Object.is")}}, не беручи до уваги знаки нулів, може бути небезпечно. Звісно, якщо на меті стоїть розрізнити <code>-0</code> та <code>+0</code>, він робить саме те, що потрібно.</p> + +<h2 id="Попередження_jsxrefObject.is_та_NaN">Попередження: {{jsxref("Object.is")}} та NaN</h2> + +<p>Специфікація {{jsxref("Object.is")}} вважає усі екземпляри {{jsxref("NaN")}} тим самим об'єктом, але, оскільки нам доступні <a href="/uk/docs/Web/JavaScript/Typed_arrays">типізовані масиви</a>, ми можемо мати окремі екземпляри, які не поводитимуться ідентично в усіх контекстах. Приклад:</p> + +<pre class="brush: js">var f2b = x => new Uint8Array(new Float64Array([x]).buffer); +var b2f = x => new Float64Array(x.buffer)[0]; +var n = f2b(NaN); +n[0] = 1; +var nan2 = b2f(n); +nan2 +> NaN +Object.is(nan2, NaN) +> true +f2b(NaN) +> Uint8Array(8) [0, 0, 0, 0, 0, 0, 248,127) +f2b(nan2) +> Uint8Array(8) [1, 0, 0, 0, 0, 0, 248,127)</pre> + +<h2 id="Див._також">Див. також</h2> + +<ul> + <li><a href="http://dorey.github.io/JavaScript-Equality-Table/">JS Comparison Table</a></li> +</ul> |