å¨ ES2015ï¼æååç¸çæ¯è¼æ¹æ³ï¼
==
)===
)ï¼è¢«ç¨æ¼ Array.prototype.indexOf
ã Array.prototype.lastIndexOf
å case
-matching%TypedArray%
å ArrayBuffer
建æ§åï¼ä»¥å Map
å Set
éç®åï¼éæå°å¨ ES2016 æ°å¢ç String.prototype.includesã
JavaScript æä¾ä¸ç¨®ä¸åç弿¯è¼éç®æä½ï¼
Object.is
(ECMAScript 2015 æ°å å
¥)è¦ç¨åªåæä½å決æ¼ä½ è¦åªç¨®é¡åçæ¯è¼ã
ç°¡å®ä¾èªªï¼ä¸è¬ç¸çæå°åå¥ä¸è´å徿¯è¼ï¼å´æ ¼ç¸çå䏿ï¼ä¹å°±æ¯èªªè¥åå¥ä¸åï¼å°±æåå³ fasleï¼ï¼Object.is
æåå´æ ¼ç¸çå忍£çäºï¼ä½æå° NaN
ã-0
å +0
ç¨ç«èçï¼å æ¤éä¸å䏿ç¸çï¼è Object.is(NaN, NaN)
åæåå³ true ãï¼ç¨ä¸è¬ç¸çæå´æ ¼ç¸çæ¯è¼å
©å NaN
ææåå³ false
ï¼å çº IEEE 754 妿¤è¦ç¯ãï¼ åè¨ï¼éä¸ç¨®å¤æ·å¿
é èæ
®ååï¼å çºä»åå¨è¨è¨ä¸ä¸è¢«èæ
®çºç¸çãå°æ¼ä»»ä½éååç©ä»¶ xãyï¼å³ä½¿ä»åæèç¸åçµæ§ï¼ä½å¦ææ¯ä¸åç©ä»¶ï¼æ¯è¼å°±ææ¯ falseã
===
ï¼
å´æ ¼ç¸çæ¯è¼å ©åå¼ï¼è被æ¯è¼çå ©åå¼é½ä¸æè½ææå ¶ä»åå¥ã妿弿¯ä¸ååå¥ï¼å°±æè¢«è¦çºä¸ç¸çãå¦æå ©å¼åå¥ç¸åä½ä¸æ¯æ¸åï¼è¥å¼ç¸åï¼åçºç¸çãæ¤å¤ï¼å¦æå ©åå¼ççºæ¸åï¼åªè¦ä»åæ¯ NaN 以å¤çåä¸å¼ï¼æè +0 å -0ï¼åçºç¸çã
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
å´æ ¼æ¯è¼é©åå¨çµå¤§å¤æ¸æ
æ³ä¸ä½¿ç¨ãå°æ¼ææéæ¸åçå¼ï¼å´æ ¼æ¯è¼å°±å¦åé¢ï¼ä¸åå¼åªç¸çæ¼èªå·±ãèæ¸åå使ç¨ç¨å¾®ä¸åçæ¹å¼ï¼ç¬¬ä¸ç¨®æ
æ³æ¯æµ®é»æ¸ 0 åæçºæ£åè² ï¼å¨è§£æ±ºæäºæ¸å¸å顿ï¼+0
å -0
æ¯ä¸åçï¼ä½å¨å¤§é¨åæ
æ³ä¸æåä¸éè¦èæ
®é種æ
å¢ï¼å æ¤å´æ ¼æ¯è¼å°ä»åè¦çºç¸åçã第äºç¨®æ
æ³æ¯éæ¸åï¼NaN
ï¼ç¨ä¾è¡¨ç¤ºæäºå®ç¾©ä¸æç¢ºçæ¸å¸åé¡çè§£ï¼ ä¾å¦ï¼è² ç¡çª®å æ£ç¡çª®ï¼å´æ ¼æ¯è¼èªçº NaN
ä¸çæ¼ä»»ä½å¼ï¼å
å«ä»æ¬èº«ãï¼(x !== x)
åªæå¨ x
æ¯ NaN
æææ¯ true
ãï¼
ä¸è¬ç¸çæå
å°æ¯è¼å¼è½ææååå¥å¾æ¯è¼ãè½æå¾ï¼å¯è½ä¸åæå
©åé½è¢«è½æï¼ï¼æ¥èé²è¡çå¹¾ä¹åå´æ ¼æ¯è¼ï¼===
ï¼ä¸æ¨£ã ä¸è¬ç¸çæå°ç¨±ï¼ A == B
çå B == A
ï¼ç¡è« A
å B
æ¯ä»éº¼ãï¼é¤äºåå¥è½æçé åºï¼
ä¸ååå¥çä¸è¬ç¸çéä½å¦ä¸è¡¨ï¼
æ¯è¼å¼ B Undefined Null Number String Boolean Object æ¯è¼å¼ A Undefinedtrue
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 ä½¿ç¨ A.toString
å A.valueOf
æ¹æ³ã
ä¸è¬ä¾èªªï¼æ ¹æ ECMAScript è¦ç¯ï¼ææç©ä»¶æè©²ä¸çæ¼ undefined
å null
ãä½å¤§å¤æ¸ç覽å¨å
許å¾å°é¨åçç©ä»¶ï¼å°¤å
¶æ¯ææé é¢ç document.all
ç©ä»¶ï¼å¨æäºæ
æ³ä¸ç¶æ undefined
ãä¸è¬ç¸çæ¯å
¶ä¸ä¸ç¨®ï¼ç¶ A æ¯åè¢«æ¨¡æ¬ æ undefined
çç©ä»¶ï¼null == A
å undefined == A
ææ¯ trueãèå¨å
¶ä»æ
æ³ä¸ç©ä»¶ä¸æçåæ¼ undefined
æ nullã
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);
é¨åéç¼è èªçºæå¥½å¥ç¨ä¸è¬ç¸çãå´æ ¼æ¯è¼æ´å®¹æé 測ï¼ä¸å çºä¸å¿ è½åï¼å æ¤æçæ´å¥½ã
åå¼ç¸çåå¼ç¸çè§£æ±ºäºæå¾ä¸åæ æ³ï¼æ¯è¼å ©å弿¯å¦åè½ç¸å ãï¼é裡ç¨äºéæ°æ¿æååçºä¾ï¼ç¶è©¦åä¿®æ¹ä¸åä¸å¯è®ç屬æ§ï¼
// æ°å¢ä¸åä¸å¯è® 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
è¦çºç¸åã
å¨ ES5ï¼ä¸è¬ç¸ç ==
å¨ Section 11.9.3, The Abstract Equality Algorithm ä¸è¦ç¯ãå´æ ¼ç¸ç ===
å¨ 11.9.6, The Strict Equality Algorithmãï¼å¯ä»¥ççï¼éå¾ç°¡çä¸å¯è®ã註ï¼å
è®å´æ ¼ç¸çãï¼ES5 ä¹å¨ Section 9.12, The SameValue Algorithm è¦ç¯ JS 弿çè¡çºãä»å¹¾ä¹åå´æ ¼ç¸ç䏿¨£ï¼é¤äº 11.9.6.4 å 9.12.4 å¨èç Number
æçä¸åãES2015 ç°¡ççæåºäº Object.is
ã
æåå¯ä»¥ç¼ç¾å¨ 11.9.6.1 ä¸ï¼é¤äº 11.9.6.1 è¦ç¯å奿ª¢æ¥ï¼å´æ ¼ç¸çè¦ç¯æ¯å¾å±¬æ¼ä¸è¬ç¸çè¦ç¯ï¼å çº 11.9.6.2â7 å 11.9.3.1.aâf ç¸æã
çè§£ç¸çæ¯è¼æ¨¡åES2015 以å¾ï¼ä½ æè¨±æå°éçæ¼åä¸çæ¼è§£è®ææ¯å½¼æ¤çãå å¼·çããæ¯å¦ï¼æäººæè¨±æèªªéçæ¼æ¯ä¸çæ¼çå»¶ä¼¸çæ¬ï¼å çºåè
åçäºæ
åå¾è
äºæ
䏿¨¡ä¸æ¨£ï¼åªå·®å¨éç®å
çåå¥è½æãèä¾ä¾èªªï¼6 == "6"
ï¼åæè
èªªï¼æäººå¯è½æè¬èªªéçæ¼æ¯åºåºï¼èä¸çæ¼æ¯å å¼·çï¼å çºå®è¦æ±å
©åéç®å
æ¯ååå¥ï¼æä»¥å®å¤äºä¸åéå¶ãè³æ¼åªåæ¯è¼å¥½çç解模åï¼å決æ¼ä½ çè§é»ã
åç®¡å¦æ¤ï¼éåæèå
§å»ºç¸åéç®åçæ¹æ³ï¼ä¸¦éæ¯å»¶ä¼¸ ES2015 ä¸ç Object.is
æ¹æ³ã Object.is
䏿¯å®ç´å°æ¯éçèãæ´å¯¬é¬ãææ¯ä¸çèãæ´å´è¬¹ãï¼ä¹ä¸é©åå°å
¶æ¾å¨å
©è
ä¹éï¼å³ï¼æ¯éçèå´è¬¹ï¼ä½è¼ä¸çè寬é¬ï¼ãæåå¯ä»¥å¾ä¸æ¹çæ¯è¼è¡¨æ ¼çå°ï¼ä¸åæ¯èµ·æºæ¼ Object.is
å¯ä»¥èç NaN
çæ¯è¼éç®ãè¦æ³¨æçæ¯ï¼å¦æ Object.is(NaN, NaN)
çéç®çµææ¯ false
ï¼æåå°±å¯ä»¥å çºå®åå -0
å +0
ççµæï¼ä½¿ç¨å¯¬é¬åå´è¬¹çç¯çä¾çå®å®æ¯æ¯ä¸çèæ´å´è¬¹çé£ä¸å段ãç¶èï¼åå¥ NaN
çæ¹å¼ä¸¦ä¸ç¢ºå¯¦ãUnfortunately, Object.is
simply has to be thought of in terms of its specific characteristics, rather than its looseness or strictness with regard to the equality operators.
==
===
Object.is
undefined
undefined
true
true
true
null
null
true
true
true
true
true
true
true
true
false
false
true
true
true
"foo"
"foo"
true
true
true
{ foo: "bar" }
x
true
true
true
0
0
true
true
true
+0
-0
true
true
false
0
false
true
false
false
""
false
true
false
false
""
0
true
false
false
"0"
0
true
false
false
"17"
17
true
false
false
[1,2]
"1,2"
true
false
false
new String("foo")
"foo"
true
false
false
null
undefined
true
false
false
null
false
false
false
false
undefined
false
false
false
false
{ foo: "bar" }
{ foo: "bar" }
false
false
false
new String("foo")
new String("foo")
false
false
false
0
null
false
false
false
0
NaN
false
false
false
"foo"
NaN
false
false
false
NaN
NaN
false
false
true
When to use Object.is
versus triple equals
Aside from the way it treats NaN
, generally, the only time Object.is
's special behavior towards zeros is likely to be of interest is in the pursuit of certain meta-programming schemes, especially regarding property descriptors when it is desirable for your work to mirror some of the characteristics of Object.defineProperty
. If your use case does not require this, it is suggested to avoid Object.is
and use ===
instead. Even if your requirements involve having comparisons between two NaN
values evaluate to true
, generally it is easier to special-case the NaN
checks (using the isNaN
method available from previous versions of ECMAScript) than it is to work out how surrounding computations might affect the sign of any zeros you encounter in your comparison.
Here's an in-exhaustive list of built-in methods and operators that might cause a distinction between -0
and +0
to manifest itself in your code:
- (unary negation)
It's obvious that negating 0
produces -0
. But the abstraction of an expression can cause -0
to creep in when you don't realize it. For example, consider:js let stoppingForce = obj.mass * -obj.velocity
If obj.velocity
is 0
(or computes to 0
), a -0
is introduced at that place and propogates out into stoppingForce
.
Math.atan2
, Math.ceil
, Math.pow
, Math.round
It's possible for a -0
to be introduced into an expression as a return value of these methods in some cases, even when no -0
exists as one of the parameters. E.g., using Math.pow
to raise -Infinity
to 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 -0
return value out of these methods in some cases where a -0
exists as one of the parameters. E.g., Math.min(-0, +0)
evalutes 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, -0
will not survive a round trip after an inverse operation. E.g., both Object.is(~~(-0), -0)
and Object.is(-0 << 2 >> 2, -0)
evaluate to false
.
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.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4