In 2001, Douglas Crockford evangelized private members design pattern and since then has been widely adopted by the Javascript community. However, are they really private?

Javascript is an extremely dynamic language in which it is possible to access a lot of things on way or another. We'll see how to get a reference to most of the "private" methods you can find in the wild.

Example

Here's a snippet of code from underscore.js. We are interested in getting a reference to the following "private" functions: lookupIterator and group.

(function() {
  /* ... */
 
  // An internal function to generate lookup iterators.
  var lookupIterator = function(value) {
    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
  };
 
  // An internal function used for aggregate "group by" operations.
  var group = function(obj, value, context, behavior) {
    var result = {};
    var iterator = lookupIterator(value || _.identity);
    each(obj, function(value, index) {
      var key = iterator.call(context, value, index, obj);
      behavior(result, key, value);
    });
    return result;
  };
 
  // Groups the object's values by a criterion. Pass either a string attribute
  // to group by, or a function that returns the criterion.
  _.groupBy = function(obj, value, context) {
    return group(obj, value, context, function(result, key, value) {
      (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
    });
  };
 
  /* ... */
}).call(this);

Here's the code to do it: (Demo on JSFiddle)

var lookupIterator;
var group;
 
_.isFunction = function() {
  lookupIterator = arguments.callee.caller;
  group = lookupIterator.caller;
};
_.groupBy();
 
console.log('lookupIterator', lookupIterator);
console.log('group', group);

The way it works is by hooking a function deep inside the internals of the module you want to break into and use arguments.callee.caller to get references to all the functions upward.

In this case, it was easy as we could hook _.isFunction. You can break into a lot of functions overriding String.prototype and using __defineGetter__.

Conclusion

Trying to break into existing Javascript code and make it do what you want is an extremely fun exercise. If this topic is of interest to you, take a look at this big list of Javascript attack vectors written by Google Caja team.

Daniel Baulig, a co-worker at Facebook, told me a little trick related to jDataView function to convert from a uint8 to a int8 in Javascript.

Here's the version I had:

function getInt8() {
  var b = this.getUint8();
  if (b > Math.pow(2, 7) - 1) {
    return b - Math.pow(2, 8);
  }
  return b;
}

Compare it to his version:

< <function getInt8() {
  return this.getUint8() << 24 >> 24;
}

I was really confused because it seems like it's doing a no-op. Here's the full explanation of why the two versions are working.

How it works?

The following table (borrowed from Wikipedia) shows how various 8 bits values are in represented with bits and how they are interpreted in unsigned and signed (using two-complement rule).

Bits uint8 int8
0000 0000 0 0
0000 0001 1 1
0000 0010 2 2
0111 1110 126 126
0111 1111 127 127
1000 0000 128 −128
1000 0001 129 −127
1000 0010 130 −126
1111 1110 254 −2
1111 1111 255 −1

Javascript doesn't natively have a 8 bit integer type, it only has a 32 bits one. When you put a 8 bit integer into a 32 bits one, Javascript is going to fill the remaining bits on the left with zeros as the following table shows.

Bits int32
0000 0000 ... 0000 0000 0
0000 0000 ... 0000 0001 1
0000 0000 ... 0000 0010 2
0000 0000 ... 0111 1110 126
0000 0000 ... 0111 1111 127
0000 0000 ... 1000 0000 128
0000 0000 ... 1000 0001 129
0000 0000 ... 1000 0010 130
0000 0000 ... 1111 1110 254
0000 0000 ... 1111 1111 255

Unfortunately, this doesn't properly handle negative numbers. Because we use two-complement, we've got to fill all the bits with 1 for negative numbers in order to have the same number in a signed 32 bits representation.

Bits int32
0000 0000 ... 0000 0000 0
0000 0000 ... 0000 0001 1
0000 0000 ... 0000 0010 2
0000 0000 ... 0111 1110 126
0000 0000 ... 0111 1111 127
1111 1111 ... 1000 0000 −128
1111 1111 ... 1000 0001 −127
1111 1111 ... 1000 0010 −126
1111 1111 ... 1111 1110 −2
1111 1111 ... 1111 1111 −1

So basically, we've got to fill the 24 remaining bits on the left with the same first bit we have: 0 for positive numbers and 1 for negative numbers.

This is when the trick comes into place. In javascript, there's a binary operator: >> Sign-propagating right shift that moves all the bits to the right and fills the missing bits with the first bit.

So all we have to do is to put our 8 good digits to the far left using << and then use the previous trick to fill the bits with the proper ones 🙂

x x < < 24 (x << 24) >> 24
0000 0000 ... 0000 0000 0000 0000 ... 0000 0000 0000 0000 ... 0000 0000
0000 0000 ... 0000 0001 0000 0001 ... 0000 0000 0000 0000 ... 0000 0001
0000 0000 ... 0000 0010 0000 0010 ... 0000 0000 0000 0000 ... 0000 0010
0000 0000 ... 0111 1110 0111 1110 ... 0000 0000 0000 0000 ... 0111 1110
0000 0000 ... 0111 1111 0111 1111 ... 0000 0000 0000 0000 ... 0111 1111
0000 0000 ... 1000 0000 1000 0000 ... 0000 0000 1111 1111 ... 1000 0000
0000 0000 ... 1000 0001 1000 0001 ... 0000 0000 1111 1111 ... 1000 0001
0000 0000 ... 1000 0010 1000 0010 ... 0000 0000 1111 1111 ... 1000 0010
0000 0000 ... 1111 1110 1111 1110 ... 0000 0000 1111 1111 ... 1111 1110
0000 0000 ... 1111 1111 1111 1111 ... 0000 0000 1111 1111 ... 1111 1111

It's often said that XML is very verbose and therefore JSON is better. I wanted to challenge that assumption and find the smallest way to represent any JSON value using XML.

Constants
true
<t/> 0
false
<f/> - 1
null
<l/> 0
Number
NaN
<n/> + 1
123.45
<n>123.45</n>
+ 6
String

""
<s/> + 2
"Abcd"
<s>Abcd</s>
+ 4
Array
[]
<a/> + 2
[1, "two", false]
<a>
  <n>1</n>
  <s>two</s>
  <f></f>
</a>
+ 4 - n
Object
{}
<o/> + 2
{
  "first": 1,
  "second": "two",
  "third": false
}
<o>
  <n k="first">1</n>
  <s k="second">two</s>
  <f k="third"></f>
</o>
+ 5 + n

As you can see, the XML counter part is a bit more verbose and less readable because of the way syntax highlighting is setup. However, while it is bigger, it isn't out of proportion bigger. The structure can be at most twice as big.

Implementation

In order to implement it, I decided to go with the same API as JSON:

  • XSON.stringify(object, formatter, space)
  • XSON.parse(string)

You can play with it on this current page or can check it out on GitHub.

The implementation was more straightforward than I expected thanks to the fact that there's a XML Parser inside browsers. However, I had to deal with nasty encoding issues 🙁

String encoding

There are some characters such as < and \0 that we want to escape because otherwise they are likely to be problematic while parsing the XML. The way to encode those characters in XML is to use the &#number; notation where number is the character code. For example a is represented by a:

> new DOMParser().parseFromString('<a>&#97;</a>', 'text/xml')
    .getElementsByTagName('a')[0].textContent
"a"

Unfortunately, you cannot express all the characters with this notation. The XML specification introduces Restricted Characters in the following ranges: [#x1-#x8], [#xB-#xC], [#xE-#x1F], [#x7F-#x84] and [#x86-#x9F]. When you try to read those characters, then the XML parser generates an error.

> new DOMParser().parseFromString('<a>&#0;</a>', 'text/xml')
    .getElementsByTagName('a')[0].textContent
"error on line 1 at column 8: xmlParseCharRef: invalid xmlChar value 0"

Instead of fighting with the XML spec, I decided to use my own encoding. I replace the character by \u0000. Where the number is an hexadecimal representation of the number padding so it has exactly four digits.

To do that, we need first to escape all the \ and can use a regex to do it in few lines of code 🙂

function encode(str) {
   return str
     .replace(/\\/g, '\\\\')
     .replace(/[\u0000-\u0008\u000b-\u001f&<>"\n\t]/g, function(c) {
       var hex = c.charCodeAt(0).toString(16);
       while (hex.length < 4) {
         hex = '0' + hex;
       }
       return '\\u' + hex;
     });
 }

Then, in order to decode it, we do the opposite: we first decode all the unicode characters and remove the escapes. In order to make sure that the unicode character was not escape, I'm using a small trick. You can count the number of \. If it's an even number, then it is not escaped, otherwise it is escaped!

function decode(str) {
  return str
    .replace(/(\\*)\\u([0-9a-f]{4})/g, function(match, backslash, n) {
      if (backslash.length % 2 !== 0) {
        return match;
      }
      return backslash + String.fromCharCode(parseInt(n, 16));
    })
    .replace(/\\\\/g, '\\');
}

Pete Hunt just showed me a cool trick today. When implementing an image gallery, chances are that you are going to let the user click on the image and based on the position, it will either display the next image or previous.

The way you would implement it without too much thought is to let the left part be for the previous action and the right part be for the next action as in the following drawing.

However, usually when you are viewing an image, you want to see the next, not the previous one. You also tend to just want to click anywhere on the image to make it go next. The previous action is not the default use case and is something you actively think about doing.

Instead of being 50%/50%, you can make the next action area bigger. Here is an example with 20%/80%.

In practice it works very well and is more user friendly that the naive one.

In a previous article I explained how CSS Percentage Background Position was working. This time I'm going to talk about the two ways to resize an image to a viewport: contain and cover. This is such a fundamental operation that I explained all the formulas and where they come from. They are the base for anything more complicated you want to do with images.

Definitions

We are going to manipulate two rectangles in this article: the image we want to display and the viewport in which we want to display it. Each rectangle has three properties: a width \(w\), a height \(h\) and an aspect ratio \(r\).

image-viewport

The aspect ratio of an image is defined by the following formula: \[r_{atio} = \frac{w_{idth}}{h_{eight}}\]

While there are an infinite amount of aspect ratios, we are going to be in contact with for major categories of aspect ratio when displaying photos on the internet.

ratios

Adapting the Image to the Viewport

Stretch the image

The naive way to adapt an image to a viewport is to set both the width and height of the image to match the viewport width and height.

stretch

However, doing that is going to stretch your image and make it look very bad.

car_resize car_resize car_resize

The problem with the previous scaling is that we didn't respect one fundamental rule: the aspect ratio must remain constant after the transformation.

\[r_{image} = r'_{image}\]

Contain

So, in order to make our image fit the viewport, we can make the image being contained in the viewport and have padding. Think black bars when you are watching a movie.

contain

In term of equations, we are setting the width of the image to be the width of the viewport: \(w'_{image} = w_{viewport}\). Since you also have \(r_{image} = r'_{image}\), and \(r'_{image} = \frac{w'_{image}}{h'_{image}}\), it gets trivial to compute the remaining dimension.

\[
h'_{image} = \frac{w_{viewport}}{r_{image}}
\]

Cover

There is another possibility, you can also make the image cover the viewport.

cover

Despite being conceptually different, the formula is nearly the same. Instead of fitting the width, we now fit the height and can compute the width the same way:

\[w'_{image} = h_{viewport} * r_{image}\]

Aspect Ratios?

In our examples so far, we considered that the image was more horizontal than the viewport. What happens if we do the opposite: switch the image and the viewport dimensions. Check out the following image with all the new equations and unknowns.

Cover

Contain

contain_cover_rato

The similarities are striking. The formulas are exactly the same but inverted, cover is now using contain formula and vis versa. It makes it even easier to implement the algorithm, only two cases to handle.

Summary

Here is a summary of the formulas if you want to implement contain and cover.

Contain Cover
\(r_{image} \le r_{viewport}\) \(w'_{image} = h_{viewport} * r_{image}\)
\(h'_{image} = h_{viewport}\)
\(w'_{image} = w_{viewport}\)
\(h'_{image} = \frac{w_{viewport}}{r_{image}}\)
\(r_{image} \ge r_{viewport}\) \(w'_{image} = w_{viewport}\)
\(h'_{image} = \frac{w_{viewport}}{r_{image}}\)
\(w'_{image} = h_{viewport} * r_{image}\)
\(h'_{image} = h_{viewport}\)

Hidden Area

We either introduced black bars or hidden some part of the photo. It's interesting to see how much it accounts for. For example, if we only hide 2% of the image, then it may not be useful to run an algorithm to find the best cropping position.

hidden area

The method is making sure that one of the dimensions is equal in both the adapted image and viewport, in this case the width. So all we are left to do is to compute the small height divided by the big height.

\[hidden = \frac{area'_{image}}{area_{viewport}} = \frac{w'_{image} * h'_{image}}{w_{viewport} * h_{viewport}} = \frac{h'_{image}}{h_{viewport}}\]

We can repeat the process for the four other cases and come up with the following summary:

Contain Cover
\(r_{image} \le r_{viewport}\) \(hidden = \frac{w'_{image}}{w_{viewport}}\) \(hidden = \frac{h_{viewport}}{h'_{image}}\)
\(r_{image} \ge r_{viewport}\) \(hidden = \frac{h'_{image}}{h_{viewport}}\) \(hidden = \frac{w_{viewport}}{w'_{image}}\)

Note that in this case, we have to evaluate the four different possibilities. As this is a bit error prone and annoying to read all the cases, we can find another way to write it down. Let's see what happens if we compare the ratios.

\[\frac{r'_{image}}{r_{viewport}} = \frac{\frac{w'_{image}}{h'_{image}}}{\frac{w_{image}}{h_{viewport}}} = \frac{w'_{image}}{h'_{image}} \frac{h_{image}}{w_{viewport}} = \frac{w'_{image}}{w_{viewport}} \frac{h_{image}}{h'_{image}}\]

We know that either the widths or the heights are equal. So it manages to find the proper two terms and the fraction. Now, nothing guarantees that they are in the good position. So we have either the result or \(\frac{1}{result}\). As we know we want a number smaller than 1, we can just take the minimum of both.

\[hidden = min\left(\frac{r_{image}}{r_{viewport}}, \frac{r_{viewport}}{r_{image}}\right)\]

Note: We were able to transform \(r'_{image}\) in to \(r_{image}\) because they are equal.

No Upscale

If you look closely at the formulas, we never actually use the width and height of the original image, we only use its aspect ratio. Therefore, if the original image is too small, it will be upscaled and appear very pixelated.

The easiest way to fix it is to compute the intended width and height, and make sure it is not bigger than the original width and height

\[w'_{image} \leftarrow min(w'_{image}, w_{image})\]\[h'_{image} \leftarrow min(h'_{image}, h_{image})\]

And here is the result:

Conclusion

I wrote this article mainly in order to have a reference of all the formulas I wrote in the code and where they came from. All the formulas are really simple (I know, they look really scared in a computer screen unfortunately) and any time you want to display an image you have to play with their width, height and area. So it's good to actually practice using them.

One key learning from this blog article should be that the aspect ratio is the most important thing that defines an image. Width and height are not actually that important as you are going to scale your image all the time. If you uses aspect ratio everywhere instead of width and height, your code is going to be a lot less error prone as we are already dealing with 2 other groups of width and heights: the scaled image and viewport size.