ÐпеÑаÑоÑÑ ÑÑавнениÑ
JavaScript пÑедоÑÑавлÑÐµÑ ÑÑи опеÑаÑоÑа ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð²ÐµÐ»Ð¸Ñин:
- ÑавенÑÑво ("двойное Ñавно") иÑполÑзÑÐµÑ ==,
- ÑÑÑогое ÑавенÑÑво ("ÑÑойное Ñавно" или "иденÑиÑно") иÑполÑзÑÐµÑ ===,
- и
Object.is(новÑеÑÑво из ECMAScript 6).
ÐÑÐ±Ð¾Ñ Ð¾Ð¿ÐµÑаÑоÑа завиÑÐ¸Ñ Ð¾Ñ Ñипа ÑÑавнениÑ, коÑоÑое Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ð¾ пÑоизвеÑÑи.
РобÑиÑ
ÑеÑÑаÑ
, двойное Ñавно пеÑед ÑÑавнением велиÑин пÑÐ¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ Ð¿Ñиведение Ñипов; ÑÑойное Ñавно ÑÑÐ°Ð²Ð½Ð¸Ð²Ð°ÐµÑ Ð²ÐµÐ»Ð¸ÑÐ¸Ð½Ñ Ð±ÐµÐ· пÑÐ¸Ð²ÐµÐ´ÐµÐ½Ð¸Ñ (еÑли велиÑÐ¸Ð½Ñ ÑазнÑÑ
Ñипов, веÑнÑÑ false, даже не ÑÑавниваÑ); Ð½Ñ Ð¸ Object.is ведÑÑ ÑÐµÐ±Ñ Ñак же, как и ÑÑойное Ñавно, но Ñо ÑпеÑиалÑной обÑабоÑкой Ð´Ð»Ñ NaN, -0 и +0, возвÑаÑÐ°Ñ false пÑи ÑÑавнении -0 и +0, и true Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑии Object.is(NaN, NaN). (Ð Ñо вÑÐµÐ¼Ñ ÐºÐ°Ðº двойное или ÑÑойное ÑавенÑÑво веÑнÑÑ false ÑоглаÑно ÑÑандаÑÑÑ IEEE 754.) СледÑÐµÑ Ð¾ÑмеÑиÑÑ, ÑÑо вÑе ÑÑи ÑазлиÑÐ¸Ñ Ð² ÑÑавнениÑÑ
пÑÐ¸Ð¼ÐµÐ½Ð¸Ð¼Ñ Ð»Ð¸ÑÑ Ð´Ð»Ñ Ð¿ÑимиÑивов. ÐÐ»Ñ Ð»ÑбÑÑ
не пÑимиÑивнÑÑ
обÑекÑов x и y, коÑоÑÑе имеÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе ÑÑÑÑкÑÑÑÑ, но пÑедÑÑавлÑÑÑ Ñобой два оÑделÑнÑÑ
обÑекÑа (пеÑеменнÑе x и y не ÑÑÑлаÑÑÑÑ Ð½Ð° один и ÑÐ¾Ñ Ð¶Ðµ обÑекÑ), вÑе опеÑаÑоÑÑ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð²ÐµÑнÑÑ false.
СÑавнение Ñ Ð¸ÑполÑзованием ==
ÐеÑед ÑÑавнением опеÑаÑÐ¾Ñ ÑавенÑÑва пÑÐ¸Ð²Ð¾Ð´Ð¸Ñ Ð¾Ð±Ðµ велиÑÐ¸Ð½Ñ Ðº обÑÐµÐ¼Ñ ÑипÑ. ÐоÑле пÑиведений (одного или обоиÑ
опеÑандов), конеÑное ÑÑавнение вÑполнÑеÑÑÑ Ñакже как и Ð´Ð»Ñ ===. ÐпеÑаÑÐ¸Ñ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ ÑиммеÑÑиÑна: A == B возвÑаÑÐ°ÐµÑ Ñо же знаÑение, ÑÑо и B == A Ð´Ð»Ñ Ð»ÑбÑÑ
знаÑений A и B.
Ð ÑледÑÑÑей ÑаблиÑе пÑÐ¸Ð²ÐµÐ´ÐµÐ½Ñ ÑезÑлÑÑаÑÑ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð¾Ð¿ÐµÑаÑоÑа ÑавенÑÑва Ð´Ð»Ñ ÑазлиÑнÑÑ Ð·Ð½Ð°Ñений:
|
ÐпеÑанд B
|
||||||
|---|---|---|---|---|---|---|---|
|
|
Undefined |
Null |
Number |
String |
Boolean |
Object |
ÐпеÑанд A |
|
true |
true |
false |
false |
false |
false |
Null |
true |
true |
false |
false |
false |
false |
|
Number |
false |
false |
A === B |
A === ToNumber(B) |
A === ToNumber(B) |
A == ToPrimitive(B) |
|
String |
false |
false |
ToNumber(A) === B |
A === B |
ToNumber(A) === ToNumber(B)
|
A == ToPrimitive(B) |
|
Boolean |
false |
false |
ToNumber(A) === B |
ToNumber(A) === ToNumber(B)
|
A === B |
ToNumber(A) == ToPrimitive(B)
|
|
Object |
false |
false |
ToPrimitive(A) == B |
ToPrimitive(A) == B |
ToPrimitive(A) == ToNumber(B)
|
A === B |
|
Ð ÑаблиÑе вÑÑе, ToNumber(A) пÑÑаеÑÑÑ Ð¿ÐµÑед ÑÑавнением пÑивеÑÑи Ñвой аÑгÑÐ¼ÐµÐ½Ñ Ðº ÑиÑлÑ. Такое поведение ÑквиваленÑно +A (ÑнаÑнÑй опеÑаÑÐ¾Ñ +). ÐÑли ToPrimitive(A) полÑÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Ð² каÑеÑÑве аÑгÑменÑа, Ñо пÑоизводÑÑÑÑ Ð¿Ð¾Ð¿ÑÑки пÑивеÑÑи его к пÑимиÑивÑ, вÑзÑÐ²Ð°Ñ Ð½Ð° нем меÑÐ¾Ð´Ñ A.toString и A.valueOf.
ТÑадиÑионно (и в ÑооÑвеÑÑÑвии Ñ ECMAScript), ни один из обÑекÑов не Ñавен undefined или null. Ðо болÑÑинÑÑво бÑаÑзеÑов позволÑÐµÑ Ð¾Ð¿ÑеделÑÐ½Ð½Ð¾Ð¼Ñ ÐºÐ»Ð°ÑÑÑ Ð¾Ð±ÑекÑов (в ÑаÑÑноÑÑи, обÑекÑам document.all Ð´Ð»Ñ Ð»Ñбой ÑÑÑаниÑÑ) ÑмÑлиÑоваÑÑ Ð·Ð½Ð°Ñение undefined. ÐпеÑаÑÐ¾Ñ ÑавенÑÑва веÑнÑÑ Ð·Ð½Ð°Ñение true Ð´Ð»Ñ null == A и undefined == A, Ñогда, и ÑолÑко Ñогда, когда обÑÐµÐºÑ ÑмÑлиÑÑÐµÑ Ð·Ð½Ð°Ñение undefined. Ðо вÑеÑ
оÑÑалÑнÑÑ
ÑлÑÑаÑÑ
обÑÐµÐºÑ Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ñавен undefined или null.
var num = 0;
var obj = new String("0");
var str = "0";
var b = false;
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);
ÐекоÑоÑÑе ÑазÑабоÑÑики ÑÑиÑаÑÑ, ÑÑо лÑÑÑе вÑегда ÑпоÑÑеблÑÑÑ Ð¾Ð¿ÐµÑаÑÐ¾Ñ ÑÑÑого ÑавенÑÑва, вмеÑÑо ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ñ Ð¿Ñиведением Ñипов. РезÑлÑÑÐ°Ñ ÑÑÑогого ÑавенÑÑва легÑе пÑедÑгадаÑÑ, да и ÑÑÐ°Ð²Ð½Ð¸Ð²Ð°Ñ Ð·Ð½Ð°ÑениÑ, без иÑ
пÑиведениÑ, можно полÑÑиÑÑ Ð²ÑигÑÑÑ Ð² ÑкоÑоÑÑи.
СÑÑогое ÑавенÑÑво Ñ Ð¸ÑполÑзованием ===
СÑÑогое Ñавно пÑовеÑÑÐµÑ Ð½Ð° ÑавенÑÑво две велиÑинÑ, пÑи ÑÑом Ñип каждой из велиÑин пеÑед ÑÑавнением не изменÑеÑÑÑ (не пÑиводиÑÑÑ). ÐÑли знаÑÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÑÑ ÑазлиÑаÑÑиеÑÑ ÑипÑ, Ñо они не могÑÑ Ð±ÑÑÑ ÑавнÑми. С дÑÑгой ÑÑоÑÐ¾Ð½Ñ Ð²Ñе не ÑиÑловÑе пеÑеменнÑе, пÑинадлежаÑие Ð¾Ð´Ð½Ð¾Ð¼Ñ ÑипÑ, ÑÑиÑаÑÑÑÑ ÑавнÑми Ð¼ÐµÐ¶Ð´Ñ Ñобой, еÑли ÑодеÑÐ¶Ð°Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе велиÑинÑ. ÐÑ Ð¸, наконеÑ, ÑиÑловÑе пеÑеменнÑе ÑÑиÑаÑÑÑÑ ÑавнÑми, еÑли они имеÑÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе знаÑениÑ, либо одна из ниÑ
+0, а вÑоÑÐ°Ñ -0. Ð Ñо же вÑемÑ, еÑли Ñ
оÑÑ Ð±Ñ Ð¾Ð´Ð½Ð° из ÑиÑловÑÑ
пеÑеменнÑÑ
ÑодеÑÐ¶Ð¸Ñ Ð·Ð½Ð°Ñение NaN, вÑÑажение веÑнÑÑ false.
var num = 0;
var obj = new String("0");
var str = "0";
var b = false;
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
ÐÑакÑиÑеÑки вÑегда Ð´Ð»Ñ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ ÑледÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð¾Ð¿ÐµÑаÑÐ¾Ñ ÑÑÑогого ÑавенÑÑва. ÐÐ»Ñ Ð²ÑеÑ
знаÑений, за иÑклÑÑением ÑиÑловÑÑ
иÑполÑзÑеÑÑÑ Ð¾ÑÐµÐ²Ð¸Ð´Ð½Ð°Ñ ÑеманÑика: велиÑина Ñавна ÑолÑко Ñама Ñебе. Ðак бÑло Ñказано вÑÑе Ð´Ð»Ñ ÑиÑловÑÑ
Ñипов можно вÑделиÑÑ Ð´Ð²Ð° оÑобÑÑ
ÑлÑÑаÑ. Ðо-пеÑвÑÑ
, ÑÑавнение +0 и -0. Ðнак Ð´Ð»Ñ Ð½ÑÐ»Ñ Ð²Ð²ÐµÐ´Ñн Ð´Ð»Ñ ÑпÑоÑÐµÐ½Ð¸Ñ Ð½ÐµÐºÐ¾ÑоÑÑÑ
вÑÑиÑлений Ñ Ð¿Ð»Ð°Ð²Ð°ÑÑей запÑÑой, однако, Ñ ÑоÑки зÑÐµÐ½Ð¸Ñ Ð¼Ð°ÑемаÑики, ÑазниÑÑ Ð¼ÐµÐ¶Ð´Ñ +0 и -0 не ÑÑÑеÑÑвÑеÑ, поÑÑÐ¾Ð¼Ñ Ð¾Ð¿ÐµÑаÑÐ¾Ñ ÑÑÑогого ÑавенÑÑва ÑÑиÑÐ°ÐµÑ Ð¸Ñ
ÑавнÑми. Ðо-вÑоÑÑÑ
, ÑÑавнение велиÑин NaN. NaN (Not a number) пÑедÑÑавлÑÐµÑ Ð¸Ð· ÑÐµÐ±Ñ Ð·Ð½Ð°Ñение не опÑеделÑнной велиÑинÑ, коÑоÑое пÑименÑеÑÑÑ Ð´Ð»Ñ Ð½Ðµ ÑÑÑко опÑеделÑннÑÑ
маÑемаÑиÑеÑкиÑ
Ð·Ð°Ð´Ð°Ñ (напÑÐ¸Ð¼ÐµÑ +â + -â). ÐÐ»Ñ Ð¾Ð¿ÐµÑаÑоÑа ÑÑÑого ÑавенÑÑва NaN не Ñавен ни одной из велиÑин, в Ñом ÑиÑле и ÑÐ°Ð¼Ð¾Ð¼Ñ Ñебе (единÑÑвеннÑй ÑлÑÑай, когда (x!==x) веÑнÑÑ true).
РавенÑÑво одинаковÑÑ Ð²ÐµÐ»Ð¸Ñин
РавенÑÑво одинаковÑÑ
велиÑин опÑеделÑÐµÑ ÑÑнкÑионалÑнÑÑ Ð¸Ð´ÐµÐ½ÑиÑноÑÑÑ Ð²Ð¾ вÑеÑ
конÑекÑÑаÑ
ÑÑавниваемÑÑ
велиÑин. (ÐаннÑй ÑпоÑоб ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð¾ÑновÑваеÑÑÑ Ð½Ð° пÑинÑипе подÑÑановки ÐаÑбаÑÑ ÐиÑков.) РаÑÑмоÑÑим пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾Ð¿ÑÑки Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½Ñемого (immutable) ÑвойÑÑва:
// Ðобавление неизменÑемого ÑвойÑÑва 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 });
}
ÐÑи попÑÑке Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½Ñемого ÑвойÑÑва, вÑзов Object.defineProperty вÑбÑоÑÐ¸Ñ Ð¸ÑклÑÑение, однако, еÑли новое ÑвойÑÑво ÑавнÑеÑÑÑ ÑÑаÑомÑ, изменений не пÑоизойдÑÑ Ð¸ иÑклÑÑение не бÑÐ´ÐµÑ Ð²ÑбÑоÑено. ÐÑли v ÑодеÑÐ¶Ð¸Ñ -0, изменений не пÑоизойдÑÑ, а знаÑиÑ, код оÑÑабоÑÐ°ÐµÑ Ð±ÐµÐ· вÑбÑоÑа иÑклÑÑений. Ðднако, еÑли же v ÑодеÑÐ¶Ð¸Ñ +0, Number.NEGATIVE_ZERO ÑÑÑаÑÐ¸Ñ ÑÐ²Ð¾Ñ Ð½ÐµÐ¸Ð·Ð¼ÐµÐ½ÑемÑÑ Ð²ÐµÐ»Ð¸ÑинÑ.
Ðменно Ð´Ð»Ñ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ и ÑекÑÑего неизменÑемÑÑ
ÑвойÑÑв иÑполÑзÑеÑÑÑ ÑÑавнение одинаковÑÑ
велиÑин, пÑедÑÑавленное меÑодом Object.is.
РавенÑÑво одинаковÑÑ Ð²ÐµÐ»Ð¸Ñин и нÑлей
ÐналогиÑно ÑавенÑÑÐ²Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²ÑÑ Ð²ÐµÐ»Ð¸Ñин, но +0 и -0 ÑÑиÑаÑÑÑÑ ÑавнÑми.
РавенÑÑво одинаковÑÑ Ð²ÐµÐ»Ð¸Ñин и нÑлей не пÑедоÑÑавлÑеÑÑÑ ÐºÐ°Ðº JavaScript API, но Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ñеализовано Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Ð¿Ð¾Ð»ÑзоваÑелÑÑкого кода:
function sameValueZero(x, y) {
if (typeof x === "number" && typeof y === "number") {
// x и y ÑÐ°Ð²Ð½Ñ (могÑÑ Ð±ÑÑÑ -0 и 0) или они оба ÑÐ°Ð²Ð½Ñ NaN
return x === y || (x !== x && y !== y);
}
return x === y;
}
РавенÑÑво одинаковÑÑ
велиÑин и нÑлей оÑлиÑаеÑÑÑ Ð¾Ñ ÑÑÑогого ÑавенÑÑва Ñем, ÑÑо пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ ÐºÐ°Ð¶Ð´Ð¾Ðµ знаÑение NaN ÑавнÑм лÑÐ±Ð¾Ð¼Ñ Ð´ÑÑÐ³Ð¾Ð¼Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NaN, а Ð¾Ñ ÑавенÑÑва одинаковÑÑ
велиÑин Ñем, ÑÑо пÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ -0 ÑавнÑм 0. Ðодобное поведение обÑÑно оказÑваеÑÑÑ ÑамÑм ÑмеÑÑнÑм пÑи поиÑке в ÑпиÑкаÑ
, оÑобенно пÑи ÑабоÑе Ñ NaN. ÐÐ°Ð½Ð½Ð°Ñ ÑÑÑаÑÐµÐ³Ð¸Ñ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð¸ÑполÑзÑеÑÑÑ Ð² меÑодаÑ
Array.prototype.includes(), TypedArray.prototype.includes(), а Ñак же в Map и Set Ð´Ð»Ñ Ð¾Ñенки ÑавенÑÑва клÑÑей.
СпеÑиÑикаÑии Ð´Ð»Ñ ÑавенÑÑва, ÑÑÑогого ÑавенÑÑва и ÑавенÑÑва одинаковÑÑ Ð²ÐµÐ»Ð¸Ñин
Ð ÑÑандаÑÑе ES5, ÑÑавнение вÑполнÑемое опеÑаÑоÑом == опиÑÑваеÑÑÑ Ð² ÑекÑии 11.9.3, The Abstract Equality Algorithm. ÐпиÑание опеÑаÑоÑа === наÑ
одиÑÑÑ Ð² ÑекÑии 11.9.6, The Strict Equality Algorithm. Ð ÑекÑии 9.12, The SameValue Algorithm ES5 опиÑÑÐ²Ð°ÐµÑ Ð¾Ð¿ÐµÑаÑÐ¸Ñ ÑÑавнение одинаковÑÑ
велиÑин Ð´Ð»Ñ Ð²Ð½ÑÑÑеннего движка JS. СÑÑогое ÑавенÑÑво и ÑавенÑÑво одинаковÑÑ
велиÑин, пÑакÑиÑеÑки одинаковÑ, за иÑклÑÑением обÑабоÑки ÑиÑловÑÑ
Ñипов. ES6 пÑÐµÐ´Ð»Ð°Ð³Ð°ÐµÑ Ð¸ÑполÑзоваÑÑ Ð°Ð»Ð³Ð¾ÑиÑм ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²ÑÑ
велиÑин ÑеÑез вÑзов Object.is.
Ðак понимаÑÑ Ð²Ñе ÑÑи ÑпоÑÐ¾Ð±Ñ ÑÑавнениÑ?
Ðо вÑÑ Ð¾Ð´Ð° ÑедакÑии ES6 ÑÑиÑалоÑÑ, ÑÑо опеÑаÑÐ¾Ñ ÑÑÑогого ÑавенÑÑва пÑоÑÑо "ÑлÑÑÑеннаÑ" веÑÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑоÑа неÑÑÑогого ÑавенÑÑва. ÐапÑимеÑ, некоÑоÑÑе ÑÑиÑали, ÑÑо == пÑоÑÑо ÑлÑÑÑÐµÐ½Ð½Ð°Ñ Ð²ÐµÑÑÐ¸Ñ === поÑомÑ, ÑÑо пеÑвÑй опеÑаÑÐ¾Ñ Ð´ÐµÐ»Ð°ÐµÑ Ð²ÑÑ Ñо же, ÑÑо и вÑоÑой, плÑÑ Ð¿Ñиведение Ñипов ÑÐ²Ð¾Ð¸Ñ Ð¾Ð¿ÐµÑандов. То еÑÑÑ 6 == "6". (Ðли же наобоÑоÑ: опеÑаÑÐ¾Ñ Ð½ÐµÑÑÑогого ÑавенÑÑва базовÑй, а опеÑаÑÐ¾Ñ ÑÑÑогого ÑавенÑÑва пÑоÑÑо его ÑлÑÑÑÐµÐ½Ð½Ð°Ñ Ð²ÐµÑÑиÑ, Ð²ÐµÐ´Ñ Ð¾Ð½ добавлÑÐµÑ ÐµÑÑ Ð¾Ð´Ð½Ð¾ ÑÑловие - ÑÑебÑеÑ, ÑÑÐ¾Ð±Ñ Ð¾Ð±Ð° опеÑанда бÑли одного и Ñого же Ñипа. Ðакой ваÑÐ¸Ð°Ð½Ñ Ð±Ð»Ð¸Ð¶Ðµ вам, завиÑÐ¸Ñ ÑолÑко Ð¾Ñ Ð²Ð°Ñей ÑоÑки зÑÐµÐ½Ð¸Ñ Ð½Ð° веÑи.)
Ðо ÑÑи ÑоÑки зÑÐµÐ½Ð¸Ñ Ñже нелÑÐ·Ñ Ð¿ÑимениÑÑ Ðº Ð½Ð¾Ð²Ð¾Ð¼Ñ Ð¼ÐµÑÐ¾Ð´Ñ ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ Object.is из новой ÑедакÑии ES6. ÐелÑÐ·Ñ ÑказаÑÑ, ÑÑо Object.is более или менее ÑÑÑог оÑноÑиÑелÑно ÑÑÑеÑÑвÑÑÑÐ¸Ñ ÑпоÑобов ÑÑавнениÑ, или ÑÑо ÑÑо неÑÑо ÑÑеднее Ð¼ÐµÐ¶Ð´Ñ Ð½Ð¸Ð¼Ð¸. Ðиже в ÑаблиÑе Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ Ð¾ÑновнÑе ÑазлиÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑоÑов ÑÑавнениÑ. Object.is инÑеÑеÑен Ñем, ÑÑо ÑазлиÑÐ°ÐµÑ -0 и +0, а Ñакже ÑÐ¼ÐµÐµÑ ÑÑавниваÑÑ Ð´Ð²Ð° не ÑиÑла NaN.
| x | y | == |
=== |
Object.is |
SameValueZero |
|---|---|---|---|---|---|
undefined |
undefined |
â
true |
â
true |
â
true |
â
true |
null |
null |
â
true |
â
true |
â
true |
â
true |
true |
true |
â
true |
â
true |
â
true |
â
true |
false |
false |
â
true |
â
true |
â
true |
â
true |
'foo' |
'foo' |
â
true |
â
true |
â
true |
â
true |
0 |
0 |
â
true |
â
true |
â
true |
â
true |
+0 |
-0 |
â
true |
â
true |
â false |
â
true |
+0 |
0 |
â
true |
â
true |
â
true |
â
true |
-0 |
0 |
â
true |
â
true |
â false |
â
true |
0n |
-0n |
â
true |
â
true |
â
true |
â
true |
0 |
false |
â
true |
â false |
â false |
â false |
"" |
false |
â
true |
â false |
â false |
â false |
"" |
0 |
â
true |
â false |
â false |
â false |
'0' |
0 |
â
true |
â false |
â false |
â false |
'17' |
17 |
â
true |
â false |
â false |
â false |
[1, 2] |
'1,2' |
â
true |
â false |
â false |
â false |
new String('foo') |
'foo' |
â
true |
â false |
â false |
â false |
null |
undefined |
â
true |
â false |
â false |
â false |
null |
false |
â false |
â false |
â false |
â false |
undefined |
false |
â false |
â false |
â false |
â false |
{ foo: 'bar' } |
{ foo: 'bar' } |
â false |
â false |
â false |
â false |
new String('foo') |
new String('foo') |
â false |
â false |
â false |
â false |
0 |
null |
â false |
â false |
â false |
â false |
0 |
NaN |
â false |
â false |
â false |
â false |
'foo' |
NaN |
â false |
â false |
â false |
â false |
NaN |
NaN |
â false |
â false |
â
true |
â
true |
Ðогда иÑполÑзоваÑÑ Object.is(), а когда ===
ÐÑобое поведение Object.is по оÑноÑÐµÐ½Ð¸Ñ Ðº нÑлÑм, веÑоÑÑно, бÑÐ´ÐµÑ Ð¿ÑедÑÑавлÑÑÑ Ð¸Ð½ÑеÑÐµÑ Ð¿Ñи ÑеализаÑии опÑеделеннÑÑ
ÑÑ
ем меÑапÑогÑаммиÑованиÑ, оÑобенно в оÑноÑении деÑкÑипÑоÑов ÑвойÑÑв, когда желаÑелÑно, ÑÑÐ¾Ð±Ñ Ð²Ð°Ñ Ð°Ð»Ð³Ð¾ÑиÑм имел Ñакое же поведение, как Object.defineProperty. Ð ÑлÑÑае, еÑли вам ÑÑого не ÑÑебÑеÑÑÑ, ÑекомендÑеÑÑÑ Ð¸Ð·Ð±ÐµÐ³Ð°ÑÑ Object.is и вмеÑÑо ÑÑого иÑполÑзоваÑÑ ===. Ðак пÑавило, даже пÑи необÑ
одимоÑÑи ÑÑÐ°Ð²Ð½ÐµÐ½Ð¸Ñ NaN-знаÑений, ÑÑÑекÑивнее вÑполниÑÑ Ð¿ÑовеÑÐºÑ ÑакиÑ
знаÑений оÑделÑно, пÑи помоÑи меÑода isNaN, Ñем вÑÑÑнÑÑÑ, как окÑÑжаÑÑие вÑÑиÑÐ»ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑÑ Ð¿Ð¾Ð²Ð»Ð¸ÑÑÑ Ð½Ð° знаки нÑлей и как ÑÑо оÑÑазиÑÑÑ Ð½Ð° ваÑем алгоÑиÑме.
ÐÐ¾Ñ Ð½ÐµÐ¿Ð¾Ð»Ð½Ñй ÑпиÑок вÑÑÑоеннÑÑ
меÑодов и опеÑаÑоÑов, пÑи иÑполÑзовании коÑоÑÑÑ
, ÑазлиÑие Ð¼ÐµÐ¶Ð´Ñ -0 и +0 Ð¼Ð¾Ð¶ÐµÑ Ð¾ÐºÐ°Ð·Ð°ÑÑÑÑ Ð²Ð°Ð¶Ð½Ñм Ð´Ð»Ñ Ð²Ð°Ñего кода:
-(unary negation)-
РаÑÑмоÑÑим ÑледÑÑÑий пÑимеÑ:
jsconst stoppingForce = obj.mass * -obj.velocity;ÐÑли
obj.velocityÑавно0(или вÑÑиÑлÑеÑÑÑ ÐºÐ°Ðº0), в ÑÑом меÑÑе возникаеÑ-0и пÑиÑваиваеÑÑÑ Ð²stoppingForce. Math.atan2,Math.ceil,Math.pow,Math.round-
In some cases, it's possible for a
-0to be introduced into an expression as a return value of these methods even when no-0exists as one of the parameters. For example, usingMath.powto raise-Infinityto the power of any negative, odd exponent evaluates to-0. Refer to the documentation for the individual methods. Math.floor,Math.max,Math.min,Math.sin,Math.sqrt,Math.tan-
It's possible to get a
-0return value out of these methods in some cases where a-0exists as one of the parameters. E.g.,Math.min(-0, +0)evaluates to-0. Refer to the documentation for the individual methods. ~,<<,>>-
Each of these operators uses the ToInt32 algorithm internally. Since there is only one representation for 0 in the internal 32-bit integer type,
-0will not survive a round trip after an inverse operation. E.g., bothObject.is(~~(-0), -0)andObject.is(-0 << 2 >> 2, -0)evaluate tofalse.
Relying on Object.is when the signedness of zeros is not taken into account can be hazardous. Of course, when the intent is to distinguish between -0 and +0, it does exactly what's desired.
Caveat: Object.is() and NaN
The Object.is specification treats all instances of NaN as the same object. However, since typed arrays are available, we can have distinct floating point representations of NaN which don't behave identically in all contexts. For example:
const f2b = (x) => new Uint8Array(new Float64Array([x]).buffer);
const b2f = (x) => new Float64Array(x.buffer)[0];
// Get a byte representation of NaN
const n = f2b(NaN);
// Change the first bit, which is the sign bit and doesn't matter for NaN
n[0] = 1;
const nan2 = b2f(n);
console.log(nan2); // NaN
console.log(Object.is(nan2, NaN)); // true
console.log(f2b(NaN)); // Uint8Array(8) [0, 0, 0, 0, 0, 0, 248, 127]
console.log(f2b(nan2)); // Uint8Array(8) [1, 0, 0, 0, 0, 0, 248, 127]