Overriding a JavaScript global function - parseInt
Written by Ian Elliot   
Monday, 20 December 2010
Article Index
Overriding a JavaScript global function - parseInt
The new parseInt
A refinement

How do you override a built-in global function in such a way that you can call the original version of the function to do most of the work?

Banner

 

There are few global functions in JavaScript but the troublesome parseInt is one of them. It can cause trouble in unexpected ways and it is even the subject of a JavaScript Puzzle see - The Day of the Integer.

The problem with parseInt is that, as well as converting a string to a numeric value, it also works with a range of number bases. You can write:

var result=parseInt(s,r);

where s is the string you want to convert and r is the radix or base of the number conversion. For example:

var result=parseInt("101",2);

returns 5 as 101 in binary (i.e. base 2) is 5.

This is very useful and not a behavior you would want to get rid of, but the problem is that the function allows you to use it without specifying the radix. If you don't specify the radix then 10 is assumed unless the string starts with "0x" when 16 (hex) is assumed or "0" when 8 (octal) is assumed. These are old conventions for writing numbers in these bases and not unreasonable, but the octal convention is all too often triggered incorrectly by dates with leading zeros.  This can result in you getting the wrong answer.

The latest version of JavaScript - ECMAScript 5 - changes this behavior and no longer assumes that a leading zero means octal. It still assumes that 0x means hex but otherwise not specifying the radix defaults to base 10.

This is good news but ECMAScript 5 isn't the norm at the moment.

So what should you do?

One solution is to redefine the global function. This isn't difficult and it is a good example of just how flexible JavaScript can be. It is also a pattern that you can use to redefine general functions and use the original definition as a base function to call to do most of the work.

First attempt

The final version of this technique uses closure and nested functions to make its magic work and there is nothing like closure to make an example difficult to understand. To add to the complication it also uses a dynamically executed function.

So in an effort to simplify things let's start by creating a function called updateparseInt which makes the change to the way the function works - then we will see how it can be "improved". Of course you might not think that the improvement is worth the extra effort and be quite happy with this first simple version.

First we need a little background. The global functions are methods of the global object - usually window. So you can write:

window.parseInt(n,r);

or

this.parseInt(n,r);

However if you use the "this" form make sure that you are not within a constructor function or this will be set to reference something other than the global object.

Just as is the case with any method you can redefine it simply by assigning an anonymous function to it.

That is after:

parseInt(n,r)=function(){ your code };

any calls to parseInt will be calls to your new function. This much is easy; the problem now is that you are committed to writing a complete new version of parseInt to make it work. This isn't much fun and seems a big waste of time as all you really want to do is modify the behaviour of the existing parseInt a little.

The solution is to keep the original reference to the  parseInt function in another variable and  use it to call the original function. With all this decided we can start to write the updateparseInt function.

First we need to check that the parseInt function exhibits the behavior we are trying to correct. If it is already working as we require then we might as well just exit the function:

updateparseInt=function()
{
if(parseInt("010")===10)return;

If we need to modify the way the function works we first need to store the original reference to the function and we might as well just use a local variable:

var tempBase=parseInt;

Banner

<ASIN:0596805527>

<ASIN:0470684143>

<ASIN:1934356670>



Last Updated ( Tuesday, 21 December 2010 )