banner



Do Template Literals Call Tostring Or Inspect

What the f*ck JavaScript?

WTFPL 2.0 NPM version Patreon Buy Me A Coffee

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:

dotJS 2012 - Brian Leroux - WTFJS

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 ![]
    • true is not equal ![], but not equal [] too
    • true is false
    • baNaNa
    • NaN is not a NaN
    • Object.is() and === weird cases
    • Information technology's a fail
    • [] is truthy, merely not true
    • goose egg is falsy, but not false
    • certificate.all is 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
    • undefined and Number
    • parseInt is a bad guy
    • Math with true and false
    • HTML comments are valid in JavaScript
    • NaN is not a number
    • [] and aught are 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 constructor holding
    • 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
    • arguments and 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 than Math.min()
    • Comparing null to 0
    • Aforementioned variable redeclaration
    • Default beliefs Array.prototype.sort()
    • resolve() won't return Promise instance
    • {}{} is undefined
    • min is greater than max
    • arguments bounden
    • An alert from hell
    • An space timeout
    • A setTimeout object
    • 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:

  1. If Type(x) is different from Type(y), return simulated.
  2. If Type(x) is Number, and then
    1. If x is NaN, return false.
    2. If y is NaN, render simulated.
    3. … … …

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.all used 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 equally certificate.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 to false when using the Strict Equality Comparison with undefined while truthful when 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_VALUE is 5e-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_INFINITY although it's not really numeric in a strict sense.

— "Why is 0 less than Number.MIN_VALUE in 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:

  1. If no arguments were passed to this function'south invocation, let due north exist +0.
  2. Else, allow n be ? ToNumber(value).
  3. In case of undefined, ToNumber(undefined) should render NaN.

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              

πŸ’‘ Explanation: This happens considering 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              

πŸ’‘ Explanation:

Information technology'southward converting zero to 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 and NaN is 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              

πŸ’‘ Explanation: If the input string begins with "0", radix is eight (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 specifies that ten (decimal) is used, just not all browsers support this yet. For this reason e'er specify a radix when using 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              

πŸ’‘ Explanation: 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 statement is true, return 1. If statement is 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 typeof Operator
  • 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 typeof Operator

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.2 and 0.3 in your program will also exist approximations to their true values. Information technology happens that the closest double to 0.2 is larger than the rational number 0.2 but that the closest double to 0.three is smaller than the rational number 0.three. The sum of 0.ane and 0.ii winds up being larger than the rational number 0.3 and 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 πŸ’… styled-components, which is popular in the React community.

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.constructor at 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:

  1. We declare x with no value, then it's undefined.
  2. Then we pack the value of x into the object property x.
  3. Then we excerpt the value of x using destructuring and want to assign information technology to y. If the value is not defined, then we're going to use 1 equally the default value.
  4. 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 try Statement

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 return Statement

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 than Math.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:

  1. If Type(ten) is Number and Type(y) is Cord, render the result of the comparison x == ! 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.

πŸ™ Give thanks you for your support! πŸ™

Service Link Activity
Patreon Become a patron
BuyMeACoffee Buy me a cup of ☕️ or πŸ₯€
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

CC 4.0

© 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

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel