Fork me on GitHub

JavaScript: The Weird Parts

Patrick Arlt

Experience Developer - ArcGIS for Developers

@patrickarlt - http://arcg.is/1wFtcQK

I'm not here to teach you something

I'm here to make your head hurt

I Have A Goal

I will convince you that you are all crazy for liking JavaScript by the end of this talk.

Example #1

var foo = 1;

function bar() {
	if (!foo) {
		var foo = 10;
	}

	alert(foo);
}

bar();

Example #2

var a = 1;

function b() {
  a = 10;

	return;

	function a() {};
}

b();

alert(a);

WTF!

Hoisting & Scope

Variable declarations and local functions are "hoisted" to the top of the function scope.

Example #1

var foo = 1;

function bar() {
	if (!foo) {
		var foo = 10;
	}

	alert(foo);
}

bar();

Example #1 Explaination

var foo = 1;

function bar() {
	var foo; // declaration hoisted

	if (!foo) { // foo is undefined
		foo = 10;
	}

	alert(foo); // 10
}

bar();

Example #2

var a = 1;

function b() {
  a = 10;

	return;

	function a() {};
}

b();

alert(a);

Example #2 Explaination

var a = 1;

function b() {
	function a() {} // a is now a local declaration in function b

  a = 10; // assign a, now in the local scope to 10

	return;
}

b();

alert(a); // 1

Lesson

There is a reason your linter yells at you about declaring all variables and functions at the top.

Infinity

Math.max() > Math.min()
false
Math.max() // > -Infinity
Math.min() // > Infinity
isFinite(42)
true
isFinite(1/0)
false
isFinite(undefined)
false
undefined == Infinity
false
isFinite(null)
true

Lession

Types

But JavaScript doesn't have types!

[] + []
""
{} + {}
NaN
[] + {}
"[object Object]"
{} + []
0
'wat' + 1
"wat1"
'wat' - 1
NaN

Lesson

This is why you use ===.

This is also why things like TypeScript exist.

Write JavaScript with only ()[]{}!+

Building Blocks

  • [] - access arrays/strings and object properties
  • () - call functions and avoid errors
  • {} - get NaN and "[object Object]"
  • + - append strings, cast things to numbers
  • ! - cast things to booleans

Booleans

  • 0 - +[]
  • true - ![]
  • false - !![]
  • 1 - +!![]

Digits

0 = +[]
1 = +!![]
2 = !+[]+!![]
3 = !+[]+!![]+!![]
4 = !+[]+!![]+!![]+!![]
5 = !+[]+!![]+!![]+!![]+!![]
6 = !+[]+!![]+!![]+!![]+!![]+!![]
7 = !+[]+!![]+!![]+!![]+!![]+!![]+!![]
8 = !+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]
9 = !+[]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]

Strings

true = !![]
false = ![]
undefined = [+[]]
NaN = +{} (object to number)
[object object] = []+{}
(!![]+{})[+[]] // > "t"

More Strings

Make strings "1e100" and "1e1000" and convert them back to numbers to get "1e+100" and Infinity. This gets you "y", "I" and "+".

SPACE, [ ] + a b c d e f i I j l n N o O r s t u y

Functions

Functions available with our current characters.

Function = array["sort"]["constructor"]
Array = array["constructor"]
Boolean = false["constructor"]
Number = 0["constructor"]
Object fom {}["constructor"]
String fom string["constructor"]
Function.prototype.call = f["call"]
String.prototype.concat = string["concat"]
Array.prototype.join = array["join"]
Array.prototype.slice = array["slice"]
Array.prototype.sort = array["sort"]

Everything Else

If you get a "p" and "%" you can use unescape("%" + HEXA_ASCII_VAL) to get any character.

([+[]]["sort"]["constructor"]("return location")()+(+{}))[3] = "p"
escape('[')[0] = "%"

With every character, digit and primitive we can build strings and execute arbitrary code using
Function('code string')().

Demo by Patricio Palladino

Why the hell would you want to do this?

Because your a hacker

JavaScript is Weird

And I Love It.

Thanks!

www.esri.com/RateMyDevSummitSession

Twitter: @patrickarlt

Slides: http://arcg.is/1wFtcQK

Esri