[Greasemonkey] Re: Can anybody explain to me the strange namespace rule?

Nikolas Coukouma atrus at atrus.org
Tue Jun 6 15:34:25 EDT 2006


Linan Wang wrote:
> I noticed that in greasemonkey scripts, to add a link in a page call a self
> defined function, have to 'hook' the function into the unsafeWindow. For
> example:
> 
> var alink=document.createElement('a');
> a.innerHTML='A link';
> a.href='javascript:self_defined_function()';
> 
> unsafeWindow.self_defined_function=function(){
>     another_function();
> };
> 
> function another_function(){}

This works fine, and doesn't touch unsafeWindow:
var a=document.createElement('a');
a.innerHTML='A link';
a.addEventListener('click', function() {
  another_function();
}, false, false);
document.body.appendChild(a);

function another_function() {
  alert("hi");
}

Although the following works just fine in my test:

var a=document.createElement('a');
a.innerHTML='A link';
a.href='javascript:self_defined_function()';
document.body.appendChild(a);

unsafeWindow.self_defined_function=function(){
    another_function();
};

function another_function(){alert("hi");}

> It is understandable, but in the 'self_defined_function', if i want to call
> another function defined in userscript, that function should NOT be hooked
> into unsafe. Why? Can anybody explain to me?

If I understand correctly, you're asking why you can write
function another_function(){alert("hi");}
instead of
unsafeWindow.another_function = function(){alert("hi");}

The reason is that functions in JavaScripts are closures. That means
they carry their scope with them. The following probably doesn't look
too weird if you're used to global variables:
count = 0;
function foo() {
  count++
  alert(count);
}
// 1
foo();
// 2
foo();

But this probably seems strange:
function foo_gen(label) {
  count = 0;
  function foo() {
    count++
    alert(count + "(" + label + ")");
  }
  return foo;
}

foo_gen returns a function. Each time foo_gen is called a new namespace
is created, so each function returned has it's own count and label:
foo_a = foo_gen("a");
// 1 (a)
foo_a();
foo_b = foo_gen("b");
// 1 (b)
foo_b();
// 2 (a)
foo_a();
// 3 (a)
foo_a();
// 2 (b)
foo_b();

I hope that helps more than it confuses.

Cheers,
-Nikolas



More information about the Greasemonkey mailing list