Do Template Literals Call Tostring Or Inspect
What the f*ck JavaScript?
A list of funny and tricky JavaScript examples
JavaScript is a great language. It has a simple syntax, large ecosystem and, what is most important, a great community.
At the aforementioned time, we all know that JavaScript is quite a funny language with tricky parts. Some of them can quickly turn our everyday chore into hell, and some of them can make us laugh out loud.
The original idea for WTFJS belongs to Brian Leroux. This list is highly inspired by his talk "WTFJS" at dotJS 2012:
Node Packaged Manuscript
You can install this handbook using npm. But run:
$ npm install -thousand wtfjs You lot should be able to run wtfjs at the command line now. This volition open the manual in your selected $PAGER. Otherwise, you lot may keep reading on here.
The source is bachelor here: https://github.com/denysdovhan/wtfjs
Translations
Currently, there are these translations of wtfjs:
- δΈζη
- ΰ€Ήिंΰ€¦ी
- FranΓ§ais
- PortuguΓͺs practice Brasil
- Polski
- Italiano
- Russian (on Habr.com)
- νκ΅μ΄
Help translating to your language
Annotation: Translations are maintained by their translators. They may non contain every example, and existing examples may be outdated.
Table of Contents
- πͺπ» Motivation
- ✍π» Notation
-
π Examples-
[]is equal![] -
trueis not equal![], but not equal[]too - true is false
- baNaNa
-
NaNis not aNaN -
Object.is()and===weird cases - Information technology's a fail
-
[]is truthy, merely nottrue -
goose eggis falsy, but notfalse -
certificate.allis an object, but information technology is undefined - Minimal value is greater than zero
- function is not a function
- Adding arrays
- Trailing commas in array
- Array equality is a monster
-
undefinedandNumber -
parseIntis a bad guy - Math with
trueandfalse - HTML comments are valid in JavaScript
-
NaNisnota number -
[]andaughtare objects - Magically increasing numbers
- Precision of
0.i + 0.2 - Patching numbers
- Comparison of three numbers
- Funny math
- Addition of RegExps
- Strings aren't instances of
String - Calling functions with backticks
- Call phone call call
- A
constructorholding - Object as a key of object'southward property
- Accessing prototypes with
__proto__ -
`${{Object}}` - Destructuring with default values
- Dots and spreading
- Labels
- Nested labels
- Insidious
effort..catch - Is this multiple inheritance?
- A generator which yields itself
- A course of class
- Not-coercible objects
- Tricky arrow functions
- Pointer functions tin can not exist a constructor
-
argumentsand arrow functions - Tricky return
- Chaining assignments on object
- Accessing object backdrop with arrays
- Null and Relational Operators
-
Number.toFixed()display unlike numbers -
Math.max()less thanMath.min() - Comparing
nullto0 - Aforementioned variable redeclaration
- Default beliefs Array.prototype.sort()
- resolve() won't return Promise instance
-
{}{}is undefined -
minis greater thanmax -
argumentsbounden - An
alertfrom hell - An space timeout
- A
setTimeoutobject - Double dot
- Extra Newness
- Why you lot should use semicolons
- Divide a string past a space
- A stringified string
- Non-strict comparison of a number to
true
-
-
π Other resources -
π€ Supporting -
π License
πͺπ» Motivation
Just for fun
— "Merely for Fun: The Story of an Accidental Revolutionary", Linus Torvalds
The master goal of this list is to collect some crazy examples and explain how they work, if possible. But because information technology's fun to learn something that we didn't know before.
If you are a beginner, yous can use these notes to become a deeper dive into JavaScript. I hope these notes will motivate y'all to spend more time reading the specification.
If you lot are a professional person developer, yous tin consider these examples every bit a great reference for all of the quirks and unexpected edges of our beloved JavaScript.
In any instance, just read this. You're probably going to observe something new.
⚠️ Notation: If you enjoy reading this document, please, consider supporting the writer of this collection.
✍π» Note
// -> is used to show the result of an expression. For example:
// > ways the result of panel.log or some other output. For example:
console . log ( "hello, earth!" ) ; // > howdy, globe! // is just a comment used for explanations. Example:
// Assigning a part to foo constant const foo = function ( ) { } ; π Examples
[] is equal ![]
Array is equal not assortment:
π‘ Explanation:
The abstract equality operator converts both sides to numbers to compare them, and both sides get the number 0 for unlike reasons. Arrays are truthy, so on the correct, the opposite of a truthy value is false, which is so coerced to 0. On the left, nevertheless, an empty array is coerced to a number without condign a boolean beginning, and empty arrays are coerced to 0, despite being truthy.
Hither is how this expression simplifies:
+ [ ] == + ! [ ] ; 0 == + false ; 0 == 0 ; truthful ; See as well [] is truthy, but not true.
- 12.5.9 Logical Not Operator (
!) - vii.2.15 Abstract Equality Comparison
true is not equal ![], but not equal [] too
Array is non equal true, but not Array is not equal truthful too; Assortment is equal false, non Array is equal false besides:
truthful == [ ] ; // -> faux truthful == ! [ ] ; // -> faux false == [ ] ; // -> true imitation == ! [ ] ; // -> true π‘ Explanation:
truthful == [ ] ; // -> false true == ! [ ] ; // -> false // According to the specification true == [ ] ; // -> fake toNumber ( true ) ; // -> 1 toNumber ( [ ] ) ; // -> 0 1 == 0 ; // -> false true == ! [ ] ; // -> false ! [ ] ; // -> faux truthful == fake ; // -> false fake == [ ] ; // -> true faux == ! [ ] ; // -> true // According to the specification fake == [ ] ; // -> true toNumber ( fake ) ; // -> 0 toNumber ( [ ] ) ; // -> 0 0 == 0 ; // -> truthful false == ! [ ] ; // -> truthful ! [ ] ; // -> imitation simulated == false ; // -> true - 7.two.xv Abstract Equality Comparing
true is false
! ! "false" == ! ! "true" ; // -> true ! ! "faux" === ! ! "true" ; // -> true π‘ Caption:
Consider this stride-by-step:
// true is 'truthy' and represented by value one (number), 'truthful' in string class is NaN. true == "true" ; // -> false false == "faux" ; // -> faux // 'fake' is not the empty string, so it'southward a truthy value ! ! "false" ; // -> true ! ! "true" ; // -> true - vii.2.15 Abstruse Equality Comparison
banana
"b" + "a" + + "a" + "a" ; // -> 'baNaNa' This is an former-school joke in JavaScript, only remastered. Hither's the original one:
"foo" + + "bar" ; // -> 'fooNaN' π‘ Explanation:
The expression is evaluated equally 'foo' + (+'bar'), which converts 'bar' to not a number.
- 12.8.3 The Addition Operator (
+) - 12.5.6 Unary + Operator
NaN is not a NaN
π‘ Explanation:
The specification strictly defines the logic behind this behavior:
- If
Type(x)is different fromType(y), return simulated.- If
Type(x)is Number, and then
- If
xis NaN, return false.- If
yis NaN, render simulated.- … … …
— 7.2.xiv Strict Equality Comparing
Following the definition of NaN from the IEEE:
Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last instance arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself.
— "What is the rationale for all comparisons returning imitation for IEEE754 NaN values?" at StackOverflow
Object.is() and === weird cases
Object.is() determines if ii values take the aforementioned value or not. It works similar to the === operator but in that location are a few weird cases:
Object . is ( NaN , NaN ) ; // -> true NaN === NaN ; // -> false Object . is ( - 0 , 0 ) ; // -> false - 0 === 0 ; // -> true Object . is ( NaN , 0 / 0 ) ; // -> true NaN === 0 / 0 ; // -> fake π‘ Explanation:
In JavaScript lingo, NaN and NaN are the aforementioned value but they're not strictly equal. NaN === NaN existence false is obviously due to historical reasons then it would probably be better to have it as it is.
Similarly, -0 and 0 are strictly equal, but they're not the same value.
For more details about NaN === NaN, run into the above case.
- Here are the TC39 specs almost Object.is
- Equality comparisons and sameness on MDN
It'due south a neglect
You lot would not believe, merely …
( ! [ ] + [ ] ) [ + [ ] ] + ( ! [ ] + [ ] ) [ + ! + [ ] ] + ( [ ! [ ] ] + [ ] [ [ ] ] ) [ + ! + [ ] + [ + [ ] ] ] + ( ! [ ] + [ ] ) [ ! + [ ] + ! + [ ] ] ; // -> 'fail' π‘ Explanation:
By breaking that mass of symbols into pieces, nosotros notice that the following blueprint occurs often:
! [ ] + [ ] ; // -> 'false' ! [ ] ; // -> fake So nosotros try adding [] to false. Simply due to a number of internal role calls (binary + Operator -> ToPrimitive -> [[DefaultValue]]) we end up converting the right operand to a string:
! [ ] + [ ] . toString ( ) ; // 'false' Thinking of a cord as an array we tin access its kickoff character via [0]:
The balance is obvious, but the i is tricky. The i in fail is grabbed by generating the string 'falseundefined' and grabbing the chemical element on alphabetize ['10'].
More examples:
+ ! [ ] // -> 0 + ! ! [ ] // -> ane ! ! [ ] // -> true ! [ ] // -> simulated [ ] [ [ ] ] // -> undefined + ! ! [ ] / + ! [ ] // -> Infinity [ ] + { } // -> "[object Object]" + { } // -> NaN - Brainfuck beware: JavaScript is after you!
- Writing a sentence without using the Alphabet — generate any phrase using JavaScript
[] is truthy, only not true
An array is a truthy value, notwithstanding, it'south non equal to true.
! ! [ ] // -> true [ ] == true // -> false π‘ Explanation:
Here are links to the corresponding sections in the ECMA-262 specification:
- 12.5.9 Logical Non Operator (
!) - 7.2.15 Abstract Equality Comparison
zilch is falsy, simply non simulated
Despite the fact that null is a falsy value, it's not equal to false.
! ! null ; // -> fake null == false ; // -> faux At the aforementioned fourth dimension, other falsy values, like 0 or '' are equal to false.
0 == false ; // -> truthful "" == simulated ; // -> truthful π‘ Caption:
The explanation is the same every bit for previous example. Here's the corresponding link:
- 7.two.15 Abstract Equality Comparing
certificate.all is an object, just it is undefined
⚠️ This is part of the Browser API and won't work in a Node.js environment⚠️
Despite the fact that document.all is an array-like object and it gives access to the DOM nodes in the page, it responds to the typeof function as undefined.
document . all instanceof Object ; // -> true typeof certificate . all ; // -> 'undefined' At the same fourth dimension, document.all is not equal to undefined.
document . all === undefined ; // -> false document . all === nil ; // -> false But at the same time:
document . all == null ; // -> true π‘ Caption:
document.allused to be a way to access DOM elements, in particular with sometime versions of IE. While it has never been a standard it was broadly used in the old age JS code. When the standard progressed with new APIs (such equallycertificate.getElementById) this API phone call became obsolete and the standard committee had to decide what to do with it. Considering of its broad use they decided to go along the API simply innovate a willful violation of the JavaScript specification. The reason why it responds tofalsewhen using the Strict Equality Comparison withundefinedwhiletruthfulwhen using the Abstract Equality Comparison is due to the willful violation of the specification that explicitly allows that.— "Obsolete features - certificate.all" at WhatWG - HTML spec — "Chapter four - ToBoolean - Falsy values" at YDKJS - Types & Grammer
Minimal value is greater than zip
Number.MIN_VALUE is the smallest number, which is greater than cipher:
Number . MIN_VALUE > 0 ; // -> truthful π‘ Explanation:
Number.MIN_VALUEis5e-324, i.east. the smallest positive number that can exist represented inside float precision, i.e. that'due south as shut as you can get to goose egg. Information technology defines the best resolution that floats tin give you.Now the overall smallest value is
Number.NEGATIVE_INFINITYalthough it's not really numeric in a strict sense.— "Why is
0less thanNumber.MIN_VALUEin JavaScript?" at StackOverflow
- xx.1.2.nine Number.MIN_VALUE
function is not a function
⚠️ A bug present in V8 v5.5 or lower (Node.js <=7)⚠️
All of you know about the annoying undefined is not a function, but what about this?
// Declare a grade which extends zero form Foo extends aught { } // -> [Role: Foo] new Foo ( ) instanceof cipher ; // > TypeError: function is not a office // > at … … … π‘ Explanation:
This is non a part of the specification. Information technology's just a bug that has at present been stock-still, so there shouldn't be a problem with information technology in the futurity.
Super constructor null of Foo is non a constructor
It's continuation of story with previous problems in modern environs (tested with Chrome 71 and Node.js v11.8.0).
class Foo extends null { } new Foo ( ) instanceof zero ; // > TypeError: Super constructor null of Foo is not a constructor π‘ Explanation:
This is not a bug because:
Object . getPrototypeOf ( Foo . prototype ) ; // -> zippo If the form has no constructor the telephone call from epitome chain. Simply in the parent has no constructor. But in instance, I'll analyze that null is an object:
typeof nix === "object" ; Therefore, yous can inherit from it (although in the earth of the OOP for such terms would have beaten me). So you can't call the null constructor. If you change this code:
class Foo extends null { constructor ( ) { console . log ( "something" ) ; } } Yous see the error:
ReferenceError: Must phone call super constructor in derived class before accessing 'this' or returning from derived constructor And if you add together super:
class Foo extends zip { constructor ( ) { console . log ( 111 ) ; super ( ) ; } } JS throws an error:
TypeError: Super constructor null of Foo is non a constructor - An caption of this issue by @geekjob
Adding arrays
What if you try to add 2 arrays?
[ 1 , 2 , 3 ] + [ 4 , five , 6 ] ; // -> '1,2,34,5,6' π‘ Explanation:
The chain happens. Step-by-step, it looks similar this:
[ 1 , two , 3 ] + [ 4 , v , six ] [ // call toString() ( 1 , two , iii ) ] . toString ( ) + [ 4 , five , 6 ] . toString ( ) ; // chain "1,2,3" + "4,5,six" ; // -> ( "1,2,34,5,6" ) ; Trailing commas in array
Yous've created an array with four empty elements. Despite all, you'll get an assortment with three elements, because of trailing commas:
permit a = [ , , , ] ; a . length ; // -> three a . toString ( ) ; // -> ',,' π‘ Explanation:
Abaft commas (sometimes called "final commas") tin can exist useful when adding new elements, parameters, or properties to JavaScript lawmaking. If you desire to add together a new property, you can merely add a new line without modifying the previously final line if that line already uses a trailing comma. This makes version-control diffs cleaner and editing code might be less troublesome.
— Abaft commas at MDN
Array equality is a monster
Array equality is a monster in JS, as you tin can see beneath:
[ ] == '' // -> truthful [ ] == 0 // -> truthful [ '' ] == '' // -> true [ 0 ] == 0 // -> true [ 0 ] == '' // -> imitation [ '' ] == 0 // -> truthful [ zip ] == '' // truthful [ cypher ] == 0 // true [ undefined ] == '' // true [ undefined ] == 0 // true [ [ ] ] == 0 // true [ [ ] ] == '' // true [ [ [ [ [ [ ] ] ] ] ] ] == '' // truthful [ [ [ [ [ [ ] ] ] ] ] ] == 0 // true [ [ [ [ [ [ null ] ] ] ] ] ] == 0 // truthful [ [ [ [ [ [ null ] ] ] ] ] ] == '' // true [ [ [ [ [ [ undefined ] ] ] ] ] ] == 0 // true [ [ [ [ [ [ undefined ] ] ] ] ] ] == '' // true π‘ Caption:
Yous should lookout very carefully for the to a higher place examples! The behaviour is described in section seven.2.fifteen Abstract Equality Comparison of the specification.
undefined and Number
If nosotros don't laissez passer any arguments into the Number constructor, nosotros'll become 0. The value undefined is assigned to formal arguments when there are no bodily arguments, and so y'all might look that Number without arguments takes undefined as a value of its parameter. However, when we pass undefined, we will go NaN.
Number ( ) ; // -> 0 Number ( undefined ) ; // -> NaN π‘ Explanation:
According to the specification:
- If no arguments were passed to this function'south invocation, let
due northexist+0. - Else, allow
nbe ?ToNumber(value). - In case of
undefined,ToNumber(undefined)should renderNaN.
Hither'south the corresponding section:
- 20.1.1 The Number Constructor
- vii.1.three ToNumber(
argument)
parseInt is a bad guy
parseInt is famous past its quirks:
parseInt ( "f*ck" ) ; // -> NaN parseInt ( "f*ck" , 16 ) ; // -> fifteen parseInt will go on parsing character-by-grapheme until information technology hits a graphic symbol it doesn't know. The f in 'f*ck' is the hexadecimal digit fifteen.
Parsing Infinity to integer is something…
// parseInt ( "Infinity" , 10 ) ; // -> NaN // ... parseInt ( "Infinity" , xviii ) ; // -> NaN... parseInt ( "Infinity" , 19 ) ; // -> 18 // ... parseInt ( "Infinity" , 23 ) ; // -> 18... parseInt ( "Infinity" , 24 ) ; // -> 151176378 // ... parseInt ( "Infinity" , 29 ) ; // -> 385849803 parseInt ( "Infinity" , xxx ) ; // -> 13693557269 // ... parseInt ( "Infinity" , 34 ) ; // -> 28872273981 parseInt ( "Infinity" , 35 ) ; // -> 1201203301724 parseInt ( "Infinity" , 36 ) ; // -> 1461559270678... parseInt ( "Infinity" , 37 ) ; // -> NaN Be conscientious with parsing null too:
parseInt ( null , 24 ) ; // -> 23
Information technology'southward converting
zeroto the cord"null"and trying to catechumen it. For radixes 0 through 23, in that location are no numerals it tin convert, so it returns NaN. At 24,"north", the 14th letter of the alphabet, is added to the numeral system. At 31,"u", the 21st letter, is added and the entire string can exist decoded. At 37 on there is no longer any valid numeral set that tin can be generated andNaNis returned.— "parseInt(null, 24) === 23… await, what?" at StackOverflow
Don't forget nigh octals:
parseInt ( "06" ) ; // 6 parseInt ( "08" ) ; // 8 if back up ECMAScript 5 parseInt ( "08" ) ; // 0 if not support ECMAScript 5 parseInt.
parseInt ever convert input to cord:
parseInt ( { toString: ( ) => 2 , valueOf: ( ) => 1 } ) ; // -> 2 Number ( { toString: ( ) => 2 , valueOf: ( ) => 1 } ) ; // -> ane Be careful while parsing floating point values
parseInt ( 0.000001 ) ; // -> 0 parseInt ( 0.0000001 ) ; // -> 1 parseInt ( ane / 1999999 ) ; // -> 5 ParseInt takes a string argument and returns an integer of the specified radix. ParseInt also strips anything after and including the outset not-digit in the string parameter. 0.000001 is converted to a string "0.000001" and the parseInt returns 0. When 0.0000001 is converted to a cord it is treated as "1e-7" and hence parseInt returns 1. 1/1999999 is interpreted equally v.00000250000125e-7 and parseInt returns 5.
Math with true and faux
Permit'due south do some math:
true + truthful ; // -> 2 ( true + true ) * ( truthful + truthful ) - true ; // -> 3 Hmmm…
π‘ Explanation:
We tin coerce values to numbers with the Number constructor. It's quite obvious that true will be coerced to one:
The unary plus operator attempts to convert its value into a number. Information technology can catechumen string representations of integers and floats, as well every bit the not-string values true, simulated, and zip. If information technology cannot parse a particular value, it will evaluate to NaN. That means we can coerce true to ane easier:
When you lot're performing improver or multiplication, the ToNumber method is invoked. According to the specification, this method returns:
If
statementis true, return 1. Ifstatementis false, return +0.
That's why we can add boolean values as regular numbers and get correct results.
Respective sections:
- 12.5.6 Unary
+Operator - 12.8.3 The Add-on Operator (
+) - 7.1.3 ToNumber(
statement)
HTML comments are valid in JavaScript
You will be impressed, but <!-- (which is known as HTML comment) is a valid comment in JavaScript.
// valid comment < ! -- valid comment too π‘ Explanation:
Impressed? HTML-similar comments were intended to allow browsers that didn't sympathize the <script> tag to degrade gracefully. These browsers, due east.k. Netscape 1.x are no longer popular. So there is really no point in putting HTML comments in your script tags anymore.
Since Node.js is based on the V8 engine, HTML-like comments are supported by the Node.js runtime too. Moreover, they're a part of the specification:
- B.1.3 HTML-similar Comments
NaN is not a number
Type of NaN is a 'number':
typeof NaN ; // -> 'number' π‘ Caption:
Explanations of how typeof and instanceof operators work:
- 12.5.5 The
typeofOperator - 12.10.4 Runtime Semantics: InstanceofOperator(
O,C)
[] and null are objects
typeof [ ] ; // -> 'object' typeof null ; // -> 'object' // nevertheless nothing instanceof Object ; // false π‘ Explanation:
The beliefs of typeof operator is divers in this section of the specification:
- 12.5.5 The
typeofOperator
Co-ordinate to the specification, the typeof operator returns a cord according to Table 35: typeof Operator Results. For null, ordinary, standard exotic and non-standard exotic objects, which do not implement [[Phone call]], it returns the string "object".
However, you lot tin check the type of an object by using the toString method.
Object . paradigm . toString . call ( [ ] ) ; // -> '[object Assortment]' Object . epitome . toString . telephone call ( new Date ( ) ) ; // -> '[object Engagement]' Object . prototype . toString . telephone call ( null ) ; // -> '[object Zippo]' Magically increasing numbers
999999999999999 ; // -> 999999999999999 9999999999999999 ; // -> 10000000000000000 10000000000000000 ; // -> 10000000000000000 10000000000000000 + 1 ; // -> 10000000000000000 10000000000000000 + 1.1 ; // -> 10000000000000002 π‘ Explanation:
This is acquired by IEEE 754-2008 standard for Binary Floating-Point Arithmetic. At this scale, it rounds to the nearest even number. Read more:
- six.1.six The Number Blazon
- IEEE 754 on Wikipedia
Precision of 0.1 + 0.2
A well-known joke. An add-on of 0.i and 0.2 is deadly precise:
0.1 + 0.ii ; // -> 0.30000000000000004 0.ane + 0.two === 0.3 ; // -> fake π‘ Explanation:
The answer for the "Is floating point math broken?" question on StackOverflow:
The constants
0.2and0.3in your program will also exist approximations to their true values. Information technology happens that the closestdoubleto0.2is larger than the rational number0.2but that the closestdoubleto0.threeis smaller than the rational number0.three. The sum of0.aneand0.iiwinds up being larger than the rational number0.3and hence disagreeing with the abiding in your lawmaking.
This trouble is and so known that there is even a website called 0.30000000000000004.com. It occurs in every language that uses floating-point math, not just JavaScript.
Patching numbers
Yous can add your own methods to wrapper objects similar Number or String.
Number . prototype . isOne = function ( ) { render Number ( this ) === ane ; } ; ( 1.0 ) . isOne ( ) ; // -> true ( i ) . isOne ( ) ; // -> true ( 2.0 ) . isOne ( ) ; // -> false ( 7 ) . isOne ( ) ; // -> imitation π‘ Caption:
Evidently, you can extend the Number object similar any other object in JavaScript. However, it's not recommended if the behavior of the defined method is not a function of the specification. Here is the list of Number's properties:
- 20.ane Number Objects
Comparison of three numbers
one < 2 < 3 ; // -> truthful 3 > 2 > 1 ; // -> imitation π‘ Explanation:
Why does this piece of work that way? Well, the trouble is in the first part of an expression. Here's how it works:
i < 2 < 3 ; // i < ii -> true true < 3 ; // true -> one 1 < 3 ; // -> true 3 > ii > 1 ; // 3 > 2 -> truthful true > 1 ; // true -> 1 one > 1 ; // -> false We tin ready this with Greater than or equal operator (>=):
Read more than about Relational operators in the specification:
- 12.ten Relational Operators
Funny math
Often the results of arithmetic operations in JavaScript might be quite unexpected. Consider these examples:
iii - one // -> 2 3 + ane // -> 4 '3' - one // -> 2 '3' + 1 // -> '31' '' + '' // -> '' [ ] + [ ] // -> '' { } + [ ] // -> 0 [ ] + { } // -> '[object Object]' { } + { } // -> '[object Object][object Object]' '222' - - '111' // -> 333 [ 4 ] * [ 4 ] // -> xvi [ ] * [ ] // -> 0 [ 4 , iv ] * [ 4 , four ] // NaN π‘ Explanation:
What'due south happening in the first four examples? Here'due south a pocket-size tabular array to understand addition in JavaScript:
Number + Number -> addition Boolean + Number -> improver Boolean + Boolean -> add-on Number + String -> concatenation Cord + Boolean -> concatenation Cord + String -> concatenation What well-nigh other examples? A ToPrimitive and ToString methods are existence implicitly called for [] and {} before addition. Read more than well-nigh evaluation process in the specification:
- 12.eight.3 The Improver Operator (
+) - 7.one.1 ToPrimitive(
input[,PreferredType]) - vii.1.12 ToString(
argument)
Notably, {} + [] here is the exception. The reason why it differs from [] + {} is that, without parenthesis, information technology is interpreted every bit a code block so a unary +, converting [] into a number. It sees the following:
{ // a code cake here } + [ ] ; // -> 0 To get the same output equally [] + {} we tin wrap it in parenthesis.
( { } + [ ] ) ; // -> [object Object] Add-on of RegExps
Did you know y'all can add numbers like this?
// Patch a toString method RegExp . prototype . toString = office ( ) { render this . source ; } / 7 / - /five/ ; // -> 2 π‘ Explanation:
- 21.2.5.10 get RegExp.image.source
Strings aren't instances of String
"str" ; // -> 'str' typeof "str" ; // -> 'string' "str" instanceof String ; // -> false π‘ Explanation:
The String constructor returns a string:
typeof String ( "str" ) ; // -> 'string' String ( "str" ) ; // -> 'str' String ( "str" ) == "str" ; // -> truthful Let's try with a new:
new String ( "str" ) == "str" ; // -> true typeof new String ( "str" ) ; // -> 'object' Object? What'due south that?
new String ( "str" ) ; // -> [String: 'str'] More information about the String constructor in the specification:
- 21.ane.1 The String Constructor
Calling functions with backticks
Let'due south declare a office which logs all params into the console:
function f (...args ) { return args ; } No doubt, you lot know y'all can call this office like this:
f ( 1 , 2 , 3 ) ; // -> [ one, 2, iii ] But did you know you tin can phone call any role with backticks?
f `truthful is ${ truthful } , false is ${ false } , array is ${ [ 1 , two , iii ] } ` ; // -> [ [ 'true is ', ', false is ', ', array is ', '' ], // -> truthful, // -> false, // -> [ 1, 2, iii ] ] π‘ Explanation:
Well, this is not magic at all if y'all're familiar with Tagged template literals. In the example above, f role is a tag for template literal. Tags before template literal allow y'all to parse template literals with a office. The first argument of a tag part contains an array of cord values. The remaining arguments are related to the expressions. Example:
role template ( strings , ...keys ) { // exercise something with strings and keys… } This is the magic backside famous library called
Link to the specification:
- 12.3.seven Tagged Templates
Call call call
Constitute by @cramforce
console . log . telephone call . call . call . call . call . apply ( a => a , [ 1 , 2 ] ) ; π‘ Explanation:
Attention, it could interruption your listen! Try to reproduce this code in your head: we're applying the call method using the apply method. Read more:
- xix.2.three.three Function.prototype.telephone call(
thisArg, ...args) - **19.ii.3.1 ** Function.paradigm.apply(
thisArg,argArray)
A constructor belongings
const c = "constructor" ; c [ c ] [ c ] ( 'console.log("WTF?")' ) ( ) ; // > WTF? π‘ Explanation:
Allow's consider this instance stride-by-footstep:
// Declare a new constant which is a cord 'constructor' const c = "constructor" ; // c is a string c ; // -> 'constructor' // Getting a constructor of string c [ c ] ; // -> [Function: String] // Getting a constructor of constructor c [ c ] [ c ] ; // -> [Office: Function] // Call the Function constructor and pass // the body of new office as an statement c [ c ] [ c ] ( 'console.log("WTF?")' ) ; // -> [Function: anonymous] // And so call this bearding role // The result is console-logging a cord 'WTF?' c [ c ] [ c ] ( 'console.log("WTF?")' ) ( ) ; // > WTF? An Object.prototype.constructor returns a reference to the Object constructor function that created the instance object. In instance with strings it is String, in case with numbers it is Number and so on.
-
Object.prototype.constructorat MDN - 19.1.iii.1 Object.prototype.constructor
Object as a primal of object's property
{ [ { } ]: { } } // -> { '[object Object]': {} } π‘ Caption:
Why does this work so? Here we're using a Computed holding name. When yous laissez passer an object betwixt those brackets, information technology coerces object to a string, and then we get the property key '[object Object]' and the value {}.
We can brand "brackets hell" like this:
( { [ { } ]: { [ { } ]: { } } } [ { } ] [ { } ] ) ; // -> {} // structure: // { // '[object Object]': { // '[object Object]': {} // } // } Read more about object literals here:
- Object initializer at MDN
- 12.ii.6 Object Initializer
Accessing prototypes with __proto__
As we know, primitives don't have prototypes. However, if we try to get a value of __proto__ for primitives, we would get this:
( 1 ) . __proto__ . __proto__ . __proto__ ; // -> null π‘ Explanation:
This happens because when something doesn't have a epitome, it will be wrapped into a wrapper object using the ToObject method. So, step-by-step:
( 1 ) . __proto__ ; // -> [Number: 0] ( 1 ) . __proto__ . __proto__ ; // -> {} ( i ) . __proto__ . __proto__ . __proto__ ; // -> zippo Hither is more information about __proto__:
- B.2.ii.one Object.prototype.proto
- 7.1.thirteen ToObject(
argument)
`${{Object}}`
What is the result of the expression below?
The answer is:
π‘ Explanation:
We defined an object with a property Object using Autograph property annotation:
Then nosotros've passed this object to the template literal, and so the toString method calls for that object. That's why we get the string '[object Object]'.
- 12.2.9 Template Literals
- Object initializer at MDN
Destructuring with default values
Consider this example:
let ten , { x: y = one } = { x } ; y ; The case to a higher place is a corking chore for an interview. What the value of y? The respond is:
π‘ Explanation:
let x , { ten: y = 1 } = { x } ; y ; // ↑ ↑ ↑ ↑ // 1 iii 2 4 With the instance above:
- We declare
xwith no value, then it'sundefined. - Then we pack the value of
xinto the object propertyx. - Then we excerpt the value of
xusing destructuring and want to assign information technology toy. If the value is not defined, then we're going to use1equally the default value. - Return the value of
y.
- Object initializer at MDN
Dots and spreading
Interesting examples could be composed with spreading of arrays. Consider this:
[...[..."..." ] ] . length ; // -> 3 π‘ Explanation:
Why 3? When we use the spread operator, the @@iterator method is called, and the returned iterator is used to obtain the values to be iterated. The default iterator for string spreads a string into characters. After spreading, we pack these characters into an array. Then we spread this array again and pack it dorsum to an assortment.
A '...' string consists with 3 . characters, so the length of resulting array is 3.
Now, step-by-step:
[...'...' ] // -> [ '.', '.', '.' ] [...[...'...' ] ] // -> [ '.', '.', '.' ] [...[...'...' ] ] . length // -> iii Plain, we can spread and wrap the elements of an array as many times every bit we want:
[...'...' ] // -> [ '.', '.', '.' ] [...[...'...' ] ] // -> [ '.', '.', '.' ] [...[...[...'...' ] ] ] // -> [ '.', '.', '.' ] [...[...[...[...'...' ] ] ] ] // -> [ '.', '.', '.' ] // and then on … Labels
Not many programmers know near labels in JavaScript. They are kind of interesting:
foo: { console . log ( "first" ) ; break foo; console . log ( "2nd" ) ; } // > first // -> undefined π‘ Explanation:
The labeled argument is used with break or continue statements. You can use a label to place a loop, and so use the break or continue statements to point whether a programme should interrupt the loop or continue its execution.
In the example above, nosotros identify a characterization foo. After that panel.log('beginning'); executes and and then we interrupt the execution.
Read more about labels in JavaScript:
- thirteen.thirteen Labelled Statements
- Labeled statements at MDN
Nested labels
a: b: c: d: due east: f: g: i , 2 , 3 , four , v ; // -> 5 π‘ Explanation:
Like to previous examples, follow these links:
- 12.16 Comma Operator (
,) - thirteen.xiii Labelled Statements
- Labeled statements at MDN
Insidious try..take hold of
What volition this expression return? two or three?
( ( ) => { try { return 2 ; } finally { return 3 ; } } ) ( ) ; The answer is three. Surprised?
π‘ Explanation:
- 13.xv The
tryStatement
Is this multiple inheritance?
Take a look at the example below:
new class F extends ( Cord , Assortment ) { } ( ) ; // -> F [] Is this a multiple inheritance? Nope.
π‘ Explanation:
The interesting role is the value of the extends clause ((String, Array)). The grouping operator always returns its last statement, so (Cord, Assortment) is actually but Array. That means we've just created a grade which extends Array.
- 14.5 Class Definitions
- 12.16 Comma Operator (
,)
A generator which yields itself
Consider this instance of a generator which yields itself:
( function * f ( ) { yield f ; } ) ( ) . next ( ) ; // -> { value: [GeneratorFunction: f], done: fake } As you tin can encounter, the returned value is an object with its value equal to f. In that case, nosotros tin do something similar this:
( function * f ( ) { yield f ; } ) ( ) . next ( ) . value ( ) . next ( ) ( // -> { value: [GeneratorFunction: f], done: false } // and once more function * f ( ) { yield f ; } ) ( ) . next ( ) . value ( ) . next ( ) . value ( ) . next ( ) ( // -> { value: [GeneratorFunction: f], washed: false } // and again function * f ( ) { yield f ; } ) ( ) . next ( ) . value ( ) . next ( ) . value ( ) . next ( ) . value ( ) . side by side ( ) ; // -> { value: [GeneratorFunction: f], washed: faux } // so on // … π‘ Caption:
To sympathize why this works that mode, read these sections of the specification:
- 25 Control Abstraction Objects
- 25.3 Generator Objects
A course of grade
Consider this obfuscated syntax playing:
typeof new course { class ( ) { } } ( ) ; // -> 'object' It seems similar we're declaring a class within of grade. Should be an fault, however, we get the cord 'object'.
π‘ Explanation:
Since ECMAScript 5 era, keywords are allowed equally property names. So think nigh it equally this simple object instance:
const foo = { form: function ( ) { } } ; And ES6 standardized autograph method definitions. Also, classes can be bearding. So if nosotros drop : function part, we're going to get:
The upshot of a default course is always a simple object. And its typeof should return 'object'.
Read more hither:
- 14.iii Method Definitions
- 14.five Class Definitions
Non-coercible objects
With well-known symbols, there's a way to get rid of type coercion. Accept a await:
function nonCoercible ( val ) { if ( val == null ) { throw TypeError ( "nonCoercible should not be chosen with zero or undefined" ) ; } const res = Object ( val ) ; res [ Symbol . toPrimitive ] = ( ) => { throw TypeError ( "Trying to coerce non-coercible object" ) ; } ; return res ; } Now we tin use this like this:
// objects const foo = nonCoercible ( { foo: "foo" } ) ; foo * 10 ; // -> TypeError: Trying to coerce non-coercible object foo + "evil" ; // -> TypeError: Trying to coerce non-coercible object // strings const bar = nonCoercible ( "bar" ) ; bar + "1" ; // -> TypeError: Trying to coerce non-coercible object bar . toString ( ) + 1 ; // -> bar1 bar === "bar" ; // -> imitation bar . toString ( ) === "bar" ; // -> true bar == "bar" ; // -> TypeError: Trying to coerce non-coercible object // numbers const baz = nonCoercible ( i ) ; baz == 1 ; // -> TypeError: Trying to coerce not-coercible object baz === 1 ; // -> faux baz . valueOf ( ) === 1 ; // -> true π‘ Explanation:
- A gist past Sergey Rubanov
- 6.one.five.1 Well-Known Symbols
Tricky arrow functions
Consider the example beneath:
permit f = ( ) => ten ; f ( ) ; // -> 10 Okay, fine, just what about this:
let f = ( ) => { } ; f ( ) ; // -> undefined π‘ Explanation:
Yous might expect {} instead of undefined. This is because the curly braces are part of the syntax of the arrow functions, so f will return undefined. It is withal possible to render the {} object direct from an arrow function, by enclosing the return value with brackets.
let f = ( ) => ( { } ) ; f ( ) ; // -> {} Pointer functions can non exist a constructor
Consider the example beneath:
let f = function ( ) { this . a = 1 ; } ; new f ( ) ; // -> f { 'a': one } Now, effort do to the same with an arrow function:
let f = ( ) => { this . a = one ; } ; new f ( ) ; // -> TypeError: f is non a constructor π‘ Caption:
Arrow functions cannot be used as constructors and will throw an error when used with new. Considering has a lexical this, and do non have a paradigm property, and then it would not make much sense.
arguments and arrow functions
Consider the example beneath:
let f = office ( ) { return arguments ; } ; f ( "a" ) ; // -> { '0': 'a' } At present, try exercise to the same with an arrow office:
let f = ( ) => arguments ; f ( "a" ) ; // -> Uncaught ReferenceError: arguments is non defined π‘ Caption:
Arrow functions are a lightweight version of regular functions with a focus on being short and lexical this. At the same time arrow functions practice not provide a binding for the arguments object. Every bit a valid alternative utilise the rest parameters to achieve the same consequence:
let f = (...args ) => args ; f ( "a" ) ; - Arrow functions at MDN.
Tricky render
render statement is as well tricky. Consider this:
( function ( ) { render { b: ten ; } } ) ( ) ; // -> undefined π‘ Explanation:
render and the returned expression must exist in the same line:
( function ( ) { render { b: ten } ; } ) ( ) ; // -> { b: 10 } This is because of a concept chosen Automated Semicolon Insertion, which automagically inserts semicolons after most newlines. In the first case, there is a semicolon inserted between the render statement and the object literal, so the function returns undefined and the object literal is never evaluated.
- eleven.9.i Rules of Automatic Semicolon Insertion
- 13.x The
returnStatement
Chaining assignments on object
var foo = { north: 1 } ; var bar = foo ; foo . x = foo = { north: 2 } ; foo . x ; // -> undefined foo ; // -> {northward: 2} bar ; // -> {n: 1, ten: {n: ii}} From right to left, {n: 2} is assigned to foo, and the result of this assignment {n: two} is assigned to foo.x, that'southward why bar is {n: 1, x: {n: 2}} every bit bar is a reference to foo. Only why foo.ten is undefined while bar.ten is not ?
π‘ Caption:
Foo and bar references the same object {north: 1}, and lvalues are resolved before assignations. foo = {n: 2} is creating a new object, and so foo is updated to reference that new object. The trick here is foo in foo.x = ... as a lvalue was resolved beforehand and still reference the old foo = {n: 1} object and update information technology by adding the x value. After that chain assignments, bar still reference the old foo object, but foo reference the new {northward: 2} object, where x is not existing.
It'southward equivalent to:
var foo = { n: ane } ; var bar = foo ; foo = { north: 2 } ; // -> {north: 2} bar . x = foo ; // -> {north: 1, ten: {n: 2}} // bar.x point to the address of the new foo object // it's not equivalent to: bar.ten = {n: 2} Accessing object properties with arrays
var obj = { property: ane } ; var array = [ "property" ] ; obj [ array ] ; // -> 1 What about pseudo-multidimensional arrays?
var map = { } ; var ten = 1 ; var y = 2 ; var z = 3 ; map [ [ 10 , y , z ] ] = true ; map [ [ x + 10 , y , z ] ] = truthful ; map [ "1,2,3" ] ; // -> true map [ "11,ii,iii" ] ; // -> true π‘ Caption:
The brackets [] operator converts the passed expression using toString. Converting a ane-element assortment to a string is akin to converting the contained element to the string:
[ "property" ] . toString ( ) ; // -> 'property' Zip and Relational Operators
nothing > 0 ; // false nothing == 0 ; // fake naught >= 0 ; // true π‘ Explanation:
Long story short, if null is less than 0 is false, then null >= 0 is true. Read in-depth explanation for this here.
Number.toFixed() display different numbers
Number.toFixed() can behave a bit foreign in unlike browsers. Check out this example:
( 0.7875 ) . toFixed ( iii ) ; // Firefox: -> 0.787 // Chrome: -> 0.787 // IE11: -> 0.788 ( 0.7876 ) . toFixed ( three ) ; // Firefox: -> 0.788 // Chrome: -> 0.788 // IE11: -> 0.788 π‘ Explanation:
While your showtime instinct may be that IE11 is correct and Firefox/Chrome are incorrect, the reality is that Firefox/Chrome are more straight obeying standards for numbers (IEEE-754 Floating Point), while IE11 is minutely disobeying them in (what is probably) an endeavour to give clearer results.
You can see why this occurs with a few quick tests:
// Confirm the odd event of rounding a 5 down ( 0.7875 ) . toFixed ( 3 ) ; // -> 0.787 // It looks like it's just a 5 when you expand to the // limits of 64-scrap (double-precision) float accuracy ( 0.7875 ) . toFixed ( xiv ) ; // -> 0.78750000000000 // But what if you get beyond the limit? ( 0.7875 ) . toFixed ( xx ) ; // -> 0.78749999999999997780 Floating bespeak numbers are not stored as a listing of decimal digits internally, only through a more complicated methodology that produces tiny inaccuracies that are usually rounded away by toString and similar calls, but are actually present internally.
In this case, that "five" on the cease was actually an extremely tiny fraction below a truthful 5. Rounding it at whatsoever reasonable length volition render it as a v... simply it is really not a five internally.
IE11, however, will study the value input with only zeros appended to the finish even in the toFixed(xx) instance, every bit it seems to exist forcibly rounding the value to reduce the troubles from hardware limits.
See for reference NOTE 2 on the ECMA-262 definition for toFixed.
- xx.i.iii.3 Number.prototype.toFixed (
fractionDigits)
Math.max() less than Math.min()
Math . min ( 1 , 4 , 7 , 2 ) ; // -> 1 Math . max ( 1 , 4 , seven , 2 ) ; // -> vii Math . min ( ) ; // -> Infinity Math . max ( ) ; // -> -Infinity Math . min ( ) > Math . max ( ) ; // -> truthful π‘ Explanation:
- Why is Math.max() less than Math.min()? past Charlie Harvey
Comparing null to 0
The following expressions seem to introduce a contradiction:
nada == 0 ; // -> simulated null > 0 ; // -> imitation nothing >= 0 ; // -> true How can nothing be neither equal to nor greater than 0, if nix >= 0 is actually true? (This also works with less than in the same way.)
π‘ Explanation:
The mode these three expressions are evaluated are all different and are responsible for producing this unexpected behavior.
First, the abstruse equality comparison goose egg == 0. Ordinarily, if this operator can't compare the values on either side properly, it converts both to numbers and compares the numbers. Then, you lot might look the following behavior:
// This is non what happens ( zippo == 0 + null ) == + 0 ; 0 == 0 ; truthful ; Nevertheless, according to a close reading of the spec, the number conversion doesn't actually happen on a side that is null or undefined. Therefore, if yous accept null on one side of the equal sign, the other side must be null or undefined for the expression to return true. Since this is not the case, false is returned.
Next, the relational comparison cypher > 0. The algorithm here, unlike that of the abstract equality operator, will convert null to a number. Therefore, we become this behavior:
null > 0 + null = + 0 0 > 0 false Finally, the relational comparing null >= 0. You could fence that this expression should be the event of null > 0 || zilch == 0; if this were the case, and so the above results would mean that this would too be simulated. However, the >= operator in fact works in a very different way, which is basically to take the opposite of the < operator. Because our example with the greater than operator higher up besides holds for the less than operator, that means this expression is actually evaluated similar so:
zilch >= 0 ; ! ( nada < 0 ) ; ! ( + null < + 0 ) ; ! ( 0 < 0 ) ; ! imitation ; truthful ; - 7.ii.12 Abstruse Relational Comparison
- 7.2.15 Abstract Equality Comparing
Same variable redeclaration
JS allows to redeclare variables:
a ; a ; // This is too valid a , a ; Works too in strict manner:
var a , a , a ; var a ; var a ; π‘ Explanation:
All definitions are merged into one definition.
- thirteen.3.2 Variable Statement
Default behavior Array.epitome.sort()
Imagine that you demand to sort an assortment of numbers.
[ 10 , 1 , 3 ] . sort ( ) ; // -> [ 1, ten, iii ] π‘ Explanation:
The default sort order is congenital upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
- 22.1.three.25 Assortment.prototype.sort ( comparefn )
Hint
Laissez passer compareFn if y'all try to sort annihilation but cord.
[ 10 , 1 , iii ] . sort ( ( a , b ) => a - b ) ; // -> [ ane, 3, 10 ] resolve() won't render Hope example
const theObject = { a: 7 } ; const thePromise = new Promise ( ( resolve , pass up ) => { resolve ( theObject ) ; } ) ; // Promise example object thePromise . and then ( value => { console . log ( value === theObject ) ; // > truthful console . log ( value ) ; // > { a: 7 } } ) ; The value which is resolved from thePromise is exactly theObject.
How about input another Promise into the resolve function?
const theObject = new Hope ( ( resolve , decline ) => { resolve ( vii ) ; } ) ; // Promise instance object const thePromise = new Promise ( ( resolve , reject ) => { resolve ( theObject ) ; } ) ; // Hope case object thePromise . and then ( value => { panel . log ( value === theObject ) ; // > false console . log ( value ) ; // > 7 } ) ; π‘ Explanation:
This role flattens nested layers of promise-like objects (e.k. a promise that resolves to a promise that resolves to something) into a single layer.
- Promise.resolve() on MDN
The specification is ECMAScript 25.6.ane.3.2 Promise Resolve Functions. But it is not quite human-friendly.
{}{} is undefined
Write them in the panel. They volition render the value defined in the concluding object.
{ } { } ; // -> undefined { } { } { } ; // -> undefined { } { } { } { } ; // -> undefined {foo: 'bar' } { } ; // -> 'bar' { } { foo: 'bar' } ; // -> 'bar' { } {foo: 'bar' } { } ; // -> 'bar' {a: 'b' } {c:' d' } { } ; // -> 'd' { a: 'b' , c: 'd' } { } ; // > SyntaxError: Unexpected token ':' ( { } { } ) ; // > SyntaxError: Unexpected token '{' π‘ Explanation:
When inspecting each {}, they returns undefined. If you inspect {foo: 'bar'}{}, you will find {foo: 'bar'} is 'bar'.
There are two meanings for {}: an object or a block. For instance, the {} in () => {} means cake. So we demand to utilize () => ({}) to render an object.
Let'south apply {foo: 'bar'} equally a block. Write this snippet in your console:
if ( true ) { foo: "bar" ; } // -> 'bar' Surprisingly, it behaviors the aforementioned! You tin guess here that {foo: 'bar'}{} is a block.
min is greater than max
I find this example hilarious:
Math . min ( ) > Math . max ( ) ; // -> true Math . min ( ) < Math . max ( ) ; // -> false π‘ Explanation:
This is a elementary 1. Allow's consider each function of this expression separately:
Math . min ( ) ; // -> Infinity Math . max ( ) ; // -> -Infinity Infinity > - Infinity ; // -> truthful Why so? Well, Math.max() is not the same matter every bit Number.MAX_VALUE. Information technology does not return the largest possible number.
Math.max takes arguments, tries to convert the to numbers, compares each 1 and then returns the largest remaining. If no arguments are given, the result is −∞. If any value is NaN, the event is NaN.
The opposite is happening for Math.min. Math.min returns ∞, if no arguments are given.
- 15.8.2.xi Math.max
- 15.8.ii.11 Math.min
- Why is
Math.max()less thanMath.min()?
arguments binding
Consider this function:
function a ( x ) { arguments [ 0 ] = "hello" ; panel . log ( x ) ; } a ( ) ; // > undefined a ( 1 ) ; // > "hi" π‘ Explanation:
arguments is an Array-like object that contains the values of the arguments passed to that function. When no arguments are passed, then at that place's no 10 to override.
- The arguments object on MDN
An warning from hell
This on is literally from hell:
[ 666 ] [ "\155\141\160" ] [ "\143\157\156\163\164\162\165\143\164\157\162" ] ( "\141\154\145\162\164(666)" ) ( 666 ) ; // warning(666) π‘ Explanation:
This i is based on octal escape sequences and multiple strings.
Any character with a character code lower than 256 (i.e. any character in the extended ASCII range) can be escaped using its octal-encoded character code, prefixed with \. An example above is basically and warning ecoded by octal escape sequances.
- Martin Kleppe tweet about it
- JavaScript character escape sequences
- Multi-Line JavaScript Strings
An infinite timeout
Guess what would happen if we ready an infinite timeout?
setTimeout ( ( ) => console . log ( "called" ) , Infinity ) ; // -> <timeoutId> // > 'called' It will executed immediately instead of infinity filibuster.
π‘ Caption:
Unremarkably, runtime stores the delay as a 32-bit signed integer internally. This causes an integer overflow, resulting in the timeout being executed immediately.
For example, in Node.js we will become this alarm:
(node:1731) TimeoutOverflowWarning: Infinity does not fit into a 32-bit signed integer. Timeout elapsing was set to 1. (Use `node --trace-warnings ...` to show where the warning was created) - WindowOrWorkerGlobalScope.setTimeout() on MDN
- Node.js Documentation on Timers
- Timers on W3C
A setTimeout object
Judge what would happen if nosotros set an callback that's not a function to setTimeout?
setTimeout ( 123 , 100 ) ; // -> <timeoutId> // > 'chosen' This is fine.
setTimeout ( '{a: ane}' , 100 ) ; // -> <timeoutId> // > 'called' This is besides fine.
setTimeout ( { a: 1 } , 100 ) ; // -> <timeoutId> // > 'Uncaught SyntaxError: Unexpected identifier setTimeout (async) (anonymous) @ VM__:one' This throws an SyntaxError.
Notation that this can easily happen if your function returns an object and you lot telephone call it here instead of passing information technology! What if the content - policy is fix to self?
setTimeout ( 123 , 100 ) ; // -> <timeoutId> // > console.error("[Study Merely] Refused to evaluate a string equally JavaScript because 'unsafe-eval' is not an allowed source of script in the post-obit Content Security Policy directive: "script-src 'written report-sample' 'self' ") The panel refuses to run information technology at all!
π‘ Explanation:
WindowOrWorkerGlobalScope.setTimeout() can be called with code every bit first argument, which volition be passed on to eval, which is bad. Eval volition coerce her input to String, and evaluate what is produced, so Objects becomes '[object Object]' which has hmmm ... an 'Unexpected identifier'!
- eval() on MDN (don't use this)
- WindowOrWorkerGlobalScope.setTimeout() on MDN
- Content Security Policy
- Timers on W3C
Double dot
Let's try to coerce a number to a string:
27. toString ( ) // > Uncaught SyntaxError: Invalid or unexpected token Maybe we should try with two dots?
27. . toString ( ) ; // -> '27' Just why doesn't first example work?
π‘ Explanation:
It'due south just a language grammar limitation.
The . character presents an ambivalence. It tin be understood to be the member operator, or a decimal, depending on its placement.
The specification's interpretation of the . character in that particular position is that information technology will be a decimal. This is defined by the numeric literal syntax of ECMAScript.
Yous must ever use parenthesis or an addition dot to brand such expression valid.
( 27 ) . toString ( ) ; // -> '27' // or 27. . toString ( ) ; // -> '27' - Usage of toString in JavaScript on StackOverflow
- Why does 10..toString() work, just 10.toString() does not?
Extra Newness
I present this as an oddity for your amusement.
course Foo extends Function { constructor ( val ) { super ( ) ; this . prototype . val = val ; } } new new Foo ( ":D" ) ( ) . val ; // -> ':D' π‘ Caption:
Constructors in JavaScript are just functions with some special treatment. Past extending Function using the class syntax yous create a class that, when instantiated, is now a office, which you can then additionally instantiate.
While non exhaustively tested, I believe the last statement can be analyzed thus:
new new Foo ( ":D" ) ( ) . val ( new newFooInstance ( ) ) . val ; veryNewFooInstance . val ; // -> ':D' As a tiny addendum, doing new Office('render "bar";') of course creates a function with the body return "bar";. Since super() in the constructor of our Foo form is calling Part's constructor, it should come as no surprise now to see that we can additionally manipulate things in there.
class Foo extends Part { constructor ( val ) { super ( ` this.val = arguments[0]; ` ) ; this . paradigm . val = val ; } } var foo = new new Foo ( ":D" ) ( "D:" ) ; foo . val ; // -> 'D:' delete foo . val ; // remove the example prop 'val', deferring dorsum to the prototype'due south 'val'. foo . val ; // -> ':D' - Class Extends Function: Extra Newness
Why you should use semicolons
Writing some standard JavaScript… and so BOOM!
grade SomeClass { [ "assortment" ] = [ ] [ "string" ] = "str" } new SomeClass ( ) . assortment ; // -> 'str' What the …?
π‘ Explanation:
Once over again, this is all thanks to the Automatic Semicolon Insertion.
An case above is basically the same every bit:
class SomeClass { [ "array" ] = ( [ ] [ "string" ] = "str" ) ; } You basically assign a string str into an array holding.
- An original tweet with an example by Ryan Cavanaugh
- TC39 meeting when they debated about information technology
Carve up a string past a space
Have you ever tried to split a string by a infinite?
"" . divide ( "" ) ; // -> [] // merely… "" . split ( " " ) ; // -> [""] π‘ Caption:
This is expected behaviour. It's responsibility is to divide the input string every fourth dimension a separator occurs in that input string. When you pass in an empty string information technology'll never detect a separator and thus return that string.
Permit's quote the specification:
The substrings are determined by searching from left to right for occurrences of
separator; these occurrences are not role of whatsoever Cord in the returned array, only serve to divide up the String value.
- 22.ane.three.21 String.paradigm.split
- An original tween with an example by Ryan Cavanaugh
- A tween with an caption past Nabil Tharwat
A stringified string
This acquired a problems that I've been solving for a few days:
JSON . stringify ( "production" ) === "production" ; // -> simulated π‘ Explanation:
Let's encounter what JSON.stringify is returning:
JSON . stringify ( "production" ) ; // -> '"production"' It is really a stringified string, so it'southward true:
'"product"' === "product" ; // -> false - ECMA-404 The JSON Data Interchange Standard.
Non-strict comparison of a number to true
ane == true ; // -> truthful // merely… Boolean ( 1.1 ) ; // -> truthful 1.one == truthful ; // -> false π‘ Explanation:
According to the specification:
The comparing x == y, where x and y are values, produces truthful or faux. Such a comparison is performed as follows:
- If
Type(ten)is Number andType(y)is Cord, render the result of the comparisonx == ! ToNumber(y).
Then this comparison is performed like this:
ane == truthful ; 1 == Number ( truthful ) ; i == one ; // -> true // but… ane.i == true ; 1.1 == Number ( true ) ; i.1 == i ; // -> false - 7.2.fifteen Abstract Equality Comparing
π Other resources
- wtfjs.com — a collection of those very special irregularities, inconsistencies and just plain painfully unintuitive moments for the language of the web.
- Wat — A lightning talk by Gary Bernhardt from CodeMash 2012
- What the... JavaScript? — Kyle Simpsons talk for Forrard ii attempts to "pull out the crazy" from JavaScript. He wants to help you produce cleaner, more elegant, more readable code, then inspire people to contribute to the open source customs.
- Zeros in JavaScript — a comparison tabular array of
==,===,+and*in JavaScript.
π€ Supporting
Hi! I work on this projection in my spare time, in add-on to my primary job. I hope you enjoy reading it. If yous do, delight, consider supporting me
Every unmarried donation is important. Your donation is gonna make a clear statement: My piece of work is valued.
| Service | Link | Activity |
|---|---|---|
| Patreon | Become a patron | |
| BuyMeACoffee | Buy me a cup of | |
| Bitcoin | 1EJsKs6rPsqa7QLoVLpe3wgcdL9Q8WmDxE | |
| Ethereum | 0x6aF39C917359897ae6969Ad682C14110afe1a0a1 | |
⚠️ Note: I alive in Ukraine and services like PayPal and Stripe don't work with Ukrainian bank accounts. This means there's no mode for me to fix up GitHub Sponsors, OpenCollective, or services relied on them. Sorry, those are the simply ways you lot can support me for now.
π License
© Denys Dovhan
Do Template Literals Call Tostring Or Inspect,
Source: https://www.npmjs.com/package/wtfjs?activeTab=readme
Posted by: johnsoncontly.blogspot.com

0 Response to "Do Template Literals Call Tostring Or Inspect"
Post a Comment