Scoping your Bookmarklet Correctly

Mar 22, 2011 javascript
This post is more than 18 months old. Since technology changes too rapidly, this content may be out of date (but that's not always the case). Please remember to verify any technical or programming information with the current release.

I’ve been lucky so far. I’ve used variable names and functions in my bookmarklet’s that weren’t that common. Then, one day, I chose a variable named something very common (x, counter, etc). I noticed that my bookmarklet accidentally overwrote some properties in the current page. Now, that could be benefit - you could want your bookmarklet to update/manage variables in the current page. However, most times I believe we don’t want that scope overlap.

Controlling Scope

In order to control that scope, its important to enclose the bookmarklet in its own anonymous function. If you leave it out there with just the normal executation in the anchor tag with javascript:, it has access to all of the global objects of this page. While in some cases, this is good, most cases this is bad.

Example of the Bad Behavior

I have a page that creates a global variable named counter. It starts out at value 3. A VERY COMPLEX function changes the value of counter. Finally, a button will show me the value of “counter” at any time.

var counter = 3;
function addToCounter()
{
  counter++;
}
addToCounter();
<button onclick="alert(counter)">Show Counter</button>

Now, let’s say I have a bookmarklet that sets a counter variable for its own usage. It alerts the counter value whenever its used. And, to be safe, I redefine counter with the var statement:

<a href="javascript:var counter=100;alert(counter)">Bookmarklet</a>

Now, let’s check the output.

  1. Load page. Counter was 3, increments to 4

  2. Click button - alerts 4

  3. Click bookmarklet. Bookmarklet counter is now 100. Alerts 100.

  4. Click button - alerts 100

As you see, even though I thought I properly scoped my variable, it now changes the global variable value - because our bookmarklet is running in the global scope of this page.

The Fix

Wrap the function in an anonymous function.

<a href="javascript:(function(){var counter=100;alert(counter)})();">Bookmarklet</a>

By doing this, the counter variable is scoped in the bookmarklet’s function scope only.

Now, clicking the button always alerts 4, and the bookmarklet always alerts 100.

Go to All Posts