迭代'window'全局变量

时间:2011-12-29 16:24:13

标签: javascript firefox greasemonkey

在普通的js中,可以迭代窗口对象 -

<html><head><script>
function one(){
}
function two(){
  for (var i in window) {
    if (i=='one') {
      alert(i);//.......................shows 'one'
    }
  }
}
two();
</script></head></html>

但是在greasemonkey中,'window'不包含函数,甚至是你在GM脚本中定义的函数:

// ==UserScript==
// @name           Page 3
// @namespace      http://xxxxxxxxxxxxxxxx
// @include        http://xxxxxxxxx.net/3.html
// ==/UserScript==
//
function one(){
}
function two(){
  for (var i in window) {
    if (i=='one') {
      alert(i);//.........shows nothing, only iterates native window props
    }
  }
}
two();

是的,我想迭代我自己的函数,而不是unsafeWindow中的函数。请注意以下工作,我不想这样做:

window.one=function one(){
}
function two(){
  for (var i in window) {
    if (i=='one') {
      alert(i);//...........ta-da! 'one'
    }
  }
}
two();

那么这个全球空间的名称是什么,我如何迭代它以及这个异常的意图和最佳实践是什么?谢谢。

更新:'this'也无法访问这些功能 -

// ==UserScript==
// @name           Page 3
// @namespace      http://xxxxxxx.net
// @include        http://xxxx.com/*
// ==/UserScript==


function do_fixes(){
  var s='';
  for (var i in this) {
    if (i=='do_fixes') {
      alert('yes');
    }
  }
  if (window!=this) {
    alert('window!=this');
  }
}

do_fixes();
alert('this script ran!');

1 个答案:

答案 0 :(得分:1)

全局对象应该可以在全局范围和自由函数中以this访问。从Greasemonkey Environment上的Greasemonkey手册页面

  

除非用户脚本头中存在@unwrap元数据命令,否则整个脚本将包含在匿名函数中,以保证脚本的标识符不会与Mozilla JavaScript沙箱中的标识符冲突。此函数包装器将所有函数定义和var变量声明(例如var i = 5;)捕获到函数的本地作用域中。但是,没有var的声明将最终出现在脚本的this对象上,该对象在Greasemonkey中是全局对象,与普通浏览器对象模型相反,window对象填充此函数

皱纹是你需要unwrap将函数的脚本添加到脚本全局(注意全局变量可以通过this访问而不需要解包)。请注意,建议@unwrap仅用于调试,因为如果变量和函数具有相同的名称,它们将与沙箱变量和函数冲突。

另一种方法是创建自己的对象来代替全局对象:

var global = {};

global.one = function () {...};
global.two = function (target) {
    for (p in global) {
        if (p == target) {
            GM_log("found " +target);
        }
    }
};
two('one');

虽然您可以在脚本全局中明确地添加函数作为方法,但这会给您带来两个世界中最糟糕的:与沙箱属性的冲突并且它不是自动的。