// Arrays and Equality
[] == ! []; // -> true
// Arrays are truthy, so ![] is false, which coerces to 0. [] coerces to 0, so 0 == 0 is true.
true == []; // -> false
true == ! []; // -> false
// true converts to 1 and [] converts to 0. 1 != 0.
false == []; // -> true
false == ! []; // -> true
// false and [] both convert to 0. 0 == 0.
// Type Coercion Oddities
!! "false" == !! "true" ; // -> true
!! "false" === !! "true" ; // -> true
// Both strings are truthy, so !! converts them to true.
"b" + "a" + + "a" + "a" ; // -> 'baNaNa'
// +"a" converts 'a' to NaN, so it becomes "ba" + NaN + "a" which is 'baNaNa'.
NaN === NaN ; // -> false
// NaN is not equal to anything, including itself.
// Object Comparison
Object . is ( NaN , NaN ); // -> true
NaN === NaN ; // -> false
Object . is ( - 0 , 0 ); // -> false
- 0 === 0 ; // -> true
// Object.is and === have different behaviors for NaN and -0.
// Fun with Syntax
[ 1 , 2 , 3 ] + [ 4 , 5 , 6 ]; // -> '1,2,34,5,6'
// Arrays are converted to strings and concatenated.
let a = [, , ,];
a . length ; // -> 3
// Trailing commas create empty slots, affecting array length.
[] == '' ; // -> true
[] == 0 ; // -> true
[ '' ] == '' ; // -> true
[ 0 ] == 0 ; // -> true
[ 0 ] == '' ; // -> false
[ '' ] == 0 ; // -> true
[[[[[[]]]]]] == '' ; // -> true
[[[[[[]]]]]] == 0 ; // -> true
// Abstract equality comparison can produce unexpected results.
// Number Coercion and Parsing
parseInt ( null , 24 ); // -> 23
// null is converted to a string and then parsed according to the specified radix.
parseInt ( 0.000001 ); // -> 0
parseInt ( 0.0000001 ); // -> 1
parseInt ( 1 / 1999999 ); // -> 5
// Parsing floats can produce unexpected results due to string conversion.
0.1 + 0.2 ; // -> 0.30000000000000004
// Floating-point arithmetic can produce imprecise results.
true + true ; // -> 2
( true + true ) * true - true ; // -> 1
// Booleans are coerced to numbers in arithmetic operations.
Number (); // -> 0
Number ( undefined ); // -> NaN
// Number without arguments returns 0, with undefined returns NaN.
// Unexpected Typeof and Instanceof
typeof NaN ; // -> 'number'
// Despite its name, NaN is of type 'number'.
typeof null ; // -> 'object'
// Null is considered an object in JavaScript, although it is a primitive value.
( 1 ). __proto__ . __proto__ . __proto__ ; // -> null
// Primitives are wrapped into their object counterparts.
const c = "constructor" ;
c [ c ][ c ]( 'console.log("WTF?")' )(); // -> WTF?
// c accesses the constructor property and calls Function.
// Miscellaneous
{} + []; // -> '[object Object]'
[] + {}; // -> '[object Object]'
// The order of operations and type coercion produce different results.
[ 10 , 1 , 3 ]. sort (); // -> [1, 10, 3]
// Default sorting converts elements to strings, sorting them lexicographically.
let f = () => {};
f (); // -> undefined
// Arrow function with empty block returns undefined.
let f = function () { return arguments ; };
f ( "a" ); // -> { '0': 'a' }
// Regular function captures arguments.
let f = () => arguments ;
f ( "a" ); // -> ReferenceError: arguments is not defined
// Arrow function does not capture arguments.
(() => {
try {
return 2 ;
} finally {
return 3 ;
}
})(); // -> 3
// finally block overrides the return statement.
new class F extends ( String , Array ) {}(); // -> F(0) []
// Extends clause uses the last argument, so class extends Array.
let x , { x : y = 1 } = { x };
y ; // -> 1
// Destructuring with default value when x is undefined.
[ ... [ ... "..." ]]. length ; // -> 3
// Spreading a string spreads its characters into an array.
foo : {
console . log ( "first" );
break foo ;
console . log ( "second" );
}
// -> 'first'
// Labeled block with break statement.
typeof new class { class () {} }(); // -> 'object'
// Keyword can be used as method name.
var foo = { n: 1 };
var bar = foo ;
foo . x = foo = { n: 2 };
foo . x ; // -> undefined
bar ; // -> { n: 1, x: { n: 2 } }
// Chain assignment with side effect.
var obj = { property: 1 };
var array = [ "property" ];
obj [ array ]; // -> 1
// Array key is coerced to string.
var nestedArray = [[[[[[[[[[ "property" ]]]]]]]]]];
obj [ nestedArray ]; // -> 1
// Array key is coerced to string.
var map = {};
var x = 1 ;
var y = 2 ;
var z = 3 ;
map [[ x , y , z ]] = true ;
map [[ x + 10 , y , z ]] = true ;
map [ "1,2,3" ]; // -> true
map [ "11,2,3" ]; // -> true
// Array keys are coerced to strings.
Math . min () > Math . max (); // -> true
Math . min () < Math . max (); // -> false
// Math.min() returns Infinity, Math.max() returns -Infinity.
null == 0 ; // -> false
null > 0 ; // -> false
null >= 0 ; // -> true
// Different comparisons yield different results.
JSON . stringify ( "production" ) === "production" ; // -> false
// JSON.stringify adds quotes to the string.
1 == true ; // -> true
Boolean ( 1.1 ); // -> true
1.1 == true ; // -> false
// Different comparisons with true and numbers.
function a ( x ) {
arguments [ 0 ] = "hello" ;
console . log ( x );
}
a (); // -> undefined
a ( 1 ); // -> "hello"
// Arguments object affects parameter value.
setTimeout (() => console . log ( "called" ), Infinity ); // -> "called"
// Infinity timeout executes immediately.
setTimeout ( 123 , 100 ); // -> <timeoutId>
// Non-function callback is converted to string and evaluated.
27. . toString (); // -> '27'
// Double dot allows to call toString on a number.
(() => {
return {
b: 10
};
})(); // -> { b: 10 }
// return and the returned expression must be in the same line.