# Tricks With Functions

Previous Top Next
So Where Are We Now? Tricks With Functions

Here, we will take advantage of the fact that a plain integer can also be treated as `Number` object. This immediately means that certain functions will automatically be available, and as long as we have encoded all the letters that make up that function’s name, we can call it.

``````(17).valueOf()
17
``````

## The toString Number Base Trick

The `Number.prototype.toString()` function can take a numeric argument in the range `2` to `36` that specifies the number base into which you’d like your number translated.

For example, we can convert `17` to a variety of number bases like this:

``````(17).toString(2)    // '10001'
(17).toString(3)    // '122'
(17).toString(4)    // '101'
(17).toString(5)    // '32'
(17).toString(6)    // '25'
(17).toString(7)    // '23'
(17).toString(8)    // '21'
(17).toString(9)    // '18'
(17).toString(10)   // '17'
(17).toString(11)   // '16'
(17).toString(12)   // '15'
(17).toString(13)   // '14'
(17).toString(14)   // '13'
(17).toString(15)   // '12'
(17).toString(16)   // '11'
(17).toString(17)   // '10'
``````

However, as soon as we specify a number base greater than 10, any number greater than 9 but less than the base will be represented as letter of the alphabet:

``````(10).toString(16)   // 'a'
(11).toString(16)   // 'b'
(12).toString(16)   // 'c'
(13).toString(16)   // 'd'
(14).toString(16)   // 'e'
(15).toString(16)   // 'f'
(16).toString(17)   // 'g'
(17).toString(18)   // 'h'
``````

And presto! We now have a way of generating all the letters from `'a'` to `'z'` — of course, this assumes that we first start with sufficient letters to spell the word `'toString'`.

For example, in base 36, 35 is `'z'`.

The only gotcha here is remembering that the number being encoded must be supplied as an integer. So, we must encode it as the concatenation of its digits. In this example `17` is encoded as `+('1' + '7') -> +'17' -> 17`.

So using our helper functions `toNum` and `concatChars`, the letter `'h'` is encoded like this:

``````const toNum = val => `+(\${val})`
const concatChars = (...idxs) => idxs.map(idx => charCache[idx]).join("+")

const encToString = concatChars('t', 'o', 'S', 't', 'r', 'i', 'n', 'g')
const base36 = toNum(concatChars(3, 6))
charCache["h"] = `(\${toNum(concatChars(1, 7))})[\${encToString}](\${base36})`
``````

In other words, the above assignment translates to asking the following question: how is `17` represented in base `18`; and the answer is `'h'`:

``````charCache["h"] = (17)["toString"](18)
``````

We can now repeat this trick as many times as needed to fill in the missing lowercase letters in our `charCache`.

## Creating a Function That Generates Functions

Here we need to take advantage of the fact that an empty array `[]` is a built-in JavaScript object that has a known set of functions.

So, this should look familiar:

``````[3, 4, 2, 1].sort()  // [1, 2, 3, 4]
``````

It should be no surprise to discover that calling an array’s `sort()` function does exactly what it says on the tin — it returns a new array with the elements in their natural sort order.

Q: Why did we choose the `sort` function?
A: Because it has a short name, and we have already encoded the letters `'s'`, `'o'`, `'r'` and `'t'` 😃

``````[].sort              // What does this give?
``````

By omitting the open/close parentheses `()` after the function name, we are no longer invoking the `sort` function; instead, what we get back is a reference to the `sort` function itself:

``````[].sort              // [Function: sort]
``````

And since functions are themselves built-in objects, we can reference the known functions belonging to the `sort` function. For instance:

``````[].sort.constructor  // [Function: Function]
``````

This might look pretty obscure, but this is actually really powerful because what we now have is a reference to the JavaScript function constructor. In other words, this is a function that can build other functions for us — all we need to supply is the source code for the new function.

One restriction here is the fact that we must already have encoded sufficient letters to be able to spell the words in the desired source code!

In the event that we are unable to derive a particular 7-bit character from some returned keyword or string, we can generate an `unescape` function, to which we pass an encoded representation of that character’s hex value.

``````const encConstructor = concatChars('c', 'o', 'n', 's', 't', 'r', 'u', 'c', 't', 'o', 'r')
const encSort = concatChars('s', 'o', 'r', 't')

// Using the function constructor we can build a function that returns a reference to the function we want to call
// []["sort"]["constructor"](<fn source code>)() -> [Function: <Fn returned by source code>]
export const encodeScript = src => `\${EMPTY_LIST}[\${encSort}][\${encConstructor}](\${encodeString(src)})()`

// []['sort']['constructor']('return unescape')() -> [Function: unescape]
const unescapeFn = encodeScript("return unescape")
``````

If we encounter a Unicode character, then we must represent it using the hexadecimal form `\uXXXX`.