October 11, 2017

Fake Javascript: House of Horror

Happy October! Welcome to the JavaScript House of Horror. Here lies hacky, unconventional, or just uncommon JavaScript prose. This is post is not recommended for small children, the highly-opinionated or ill-tempered.

Error handling

Skip Google and get answers immediately.

try {
  something()
} catch (e) {
  window.location.href = (
    "https://stackoverflow.com/" +
    "search?q=[js]+" +
    e.message
  )
}

This innovative solution was first suggested here.

Of course, the easy way out would be to handle errors like this globally:

window.onerror = e =>
  window.location.href = (
    "https://stackoverflow.com/" +
    "search?q=[js]+" +
    e.message
  )

Also, don’t forget to use encodeURIComponent(e.message) before you implement this ✨feature✨ in production.

Bracket magic

++[[]][+[]] + [+[]] // returns "10"

See a thorough explanation here.

JSF*ck

Run the code here.

Here are the basic building blocks for JSF*ck:

![] === false
[]+[] === ""
![]+[] === "false"
+[] === 0

So imagine that we can stringify JavaScript return values like ‘undefined’ and ‘true’. And with numeric values, we can extract specific index values from these words. This is a more thorough explanation.

Here’s a similar one: Emoticons or JavaScript?

゚ω゚ノ= /`m´)ノ ~┻━┻   //*´∇`*/ ['_']; o=(゚ー゚)  =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');

Run the code here or check out the encoder.

However, don’t fall in love with brackets just yet. Comparing array equality should break your spirits:

[] == ''   // true
[] == 0    // true
[''] == '' // true
[0] == 0   // true
[0] == ''  // false
[''] == 0  // true

[null] == ''      // true
[null] == 0       // true
[undefined] == '' // true
[undefined] == 0  // true

[[]] == 0  // true
[[]] == '' // true

[[[[[[]]]]]] == '' // true
[[[[[[]]]]]] == 0  // true

[[[[[[ null ]]]]]] == 0  // true
[[[[[[ null ]]]]]] == '' // true

[[[[[[ undefined ]]]]]] == 0  // true
[[[[[[ undefined ]]]]]] == '' // true

The ECMA spec describes this behavior in Abstract Equality Comparison.

JavaScript Labyrinth

See the Pen JavaScript Labyrinth by Brett (@brettinternet) on CodePen.

isPrime()

function isPrime(n) {
  return !/^.?$|^(..+?)\1+$/.test("1".repeat(n))
}

Here is an explanation of a similar solution with a regular expression.

Draw the box model on a webpage

;[].forEach.call($$("*"), function(a) {
  a.style.outline = "1px solid #" + (~~(Math.random() * (1 << 24))).toString(16)
})

box model from js input

The code above is essentially translated into:

Array.prototype.forEach.call(
  document.querySelectorAll("*"),
  dom =>
    (dom.style.outline = `1px solid #${parseInt(
      Math.random() * Math.pow(2, 24)
    ).toString(16)}`)
)

Generate a random string

Math.random()
  .toString(16)
  .substring(2) // "d37a43dda9777"
Math.random()
  .toString(36)
  .substring(2) // "plwldktp48"

Make a deep copy object

Because objects are reference types, referencing an object to a new variable and changing the object referenced by that variable will still alter the original object. However, here’s an unorthodox way to deep copy that object to a new space in memory.

var a = {
  a: 1,
  b: { c: 1, d: 2 },
}
var b = JSON.parse(JSON.stringify(a))

Implicit type conversions

Here’s a good example of type conversion without using Number, parseInt and parseFloat:

let a = "1" + a // 1
parseInt(0.0000004) === 4 // true
;[1, 2, 3] + [4, 5, 6] // '1,2,34,5,6'

Here the concatenation essentially works .toString() on each of the arrays including the values and the comma separators, and then works "1,2,3" + "4,5,6".

Concatenation has additional silly behavior with the + operator. While "3" - 1 is 2, "3" + 1 is "31".

"" + "" // ""
[] + [] // ""
{} + [] // 0
[] + {} // "[object Object]"
{} + {} // "[object Object][object Object]"

So, concatenation depends on the types involved in the operation:

  • Number + Number :arrow_right: addition
  • Boolean + Number :arrow_right: addition
  • Boolean + Boolean :arrow_right: addition
  • Number + String :arrow_right: concatenation
  • String + Boolean :arrow_right: concatenation
  • String + String :arrow_right: concatenation

There’s further reading from the ECMA spec.

JavaScript floating point inaccuracies

1 + 2 is 3, right? Not with floating point values…

0.1 + 0.2 == 0.3 // false

Here, 0.1 and 0.2are not accurate floating point representations, instead they evaluate to 0.30000000000000004. This is essentially where it’s advantageous to set a predefined precision value with Number.EPSILON (related). Check out Is floating point math broken? and 0.30000000000000004.com.

Terse conditional assignment

var a = b && 1 is the same as:

if (b) {
  a = 1
} else {
  a = b
}

var a = b || 1 is the same as:

if (b) {
  a = b
} else {
  a = 1
}

Types

Document.all, an undefined object?

document.all instanceof Object // true
typeof document.all // undefined

However…

document.all === undefined // false

Here’s an explanation of this obsolete feature, which used to be used to access DOM elements in older versions of IE.

To be a number or not

typeof NaN // number

Strings aren’t Strings?

typeof "str" // "string"
"str" instanceof String // false

true evaluated as 1

true +
  true(
    // 2
    true + true
  ) *
    (true + true) -
  true // 3

When true is coerced to a number (Number(true)), it’s evaluated to a truthy value as 1.

1 < 2 < 3 // true
3 > 2 > 1 // false

The expression above is evaluated from left to right. Since 1 < 2 is true, and true => 1 and 1 < 3, the first line is true. However, as true is evaluated in the second line, 1 > 1 is false (related).

Functions invoked with backticks

First, set up a function that returns our arguments such that fn(1, 2, 3) returns [1, 2, 3]:

function fn(...args) {
  return args
}
fn`first arg is an array ${true} separated by ${1} inserted values`
// [ [ 'first arg is an array ', ' separated by ', ' inserted values' ],
// true, 1]

This is the nature of Tagged template literals and it’s the magic behind libraries like styled-components.

Try..catch

Will 1 or 2 be returned from the following expression?

(() => {
  try {
    return 1
  } finally {
    return 2
  }
})()

2 is returned. See finally’s role in the try..catch in the spec.


I hope you’re thoroughly frightened. Happy Halloween!

>Edit on GitHub·Comment·Twitter icon