2

我有一个在 FireFox 中使用 unsafeWindow 的脚本,因为它不起作用,我已经搜索了另一个选项,并找到了它,我只是想知道:如何将我的用户脚本中的变量用于 unsafeWindow 解决方法?

我的代码是:

// ==UserScript==
// @name   Test
// @description  Test
// @include   http://www.google*
// ==/UserScript==

var toAlert = "This is what I want to alert...";
alert("Before implementation...");
contentEval( function(){ alert(toAlert);});
alert("And after...");
function contentEval(source) {
  // Check for function input.
  if ('function' == typeof source) {
    // Execute this function with no arguments, by adding parentheses.
    // One set around the function, required for valid syntax, and a
    // second empty set calls the surrounded function.
    source = '(' + source + ')();'
  }

  // Create a script node holding this  source code.
  var script = document.createElement('script');
  script.setAttribute("type", "application/javascript");
  script.textContent = source;

  // Insert the script node into the page, so it will run, and immediately
  // remove it to clean up.
  document.body.appendChild(script);
  document.body.removeChild(script);
}

它不起作用......我做错了什么?

4

1 回答 1

4

toAlert如果碰巧在页面的全局范围内定义了您的脚本,它将起作用。

在 Chrome 中,扩展程序/Greasemonkey JavaScript 不能与页面 JavaScript 共享变量或闭包。
这就是为什么您不能从扩展范围到页面范围直接注入该函数,而必须从源字符串重新创建它。

这意味着如果您在页面范围内创建函数,则函数所需的任何变量或函数必须:

  1. 已经在全球范围内出现在源页面中。
    或者
  2. 也被编写到源页面中。

例如,像这样修改你的代码......

//-- Must recreate the variable that the function requires.
scriptStr  = 'var toAlert="' + toAlert +'";';

//-- Now the function.
scriptStr += '(' + source.toString() + ')();'

var script = document.createElement('script');
script.textContent = scriptStr;

...有效,但这种方法显然会变得混乱。

明智的做法是:
(A) 将所有 JavaScript 保留在扩展中;不要与页面的 JavaScript 交互。

或者 (B) 如果您必须与页面的 JS 交互,或者加载像 jQuery 这样的库,则将所有代码放在一个 main() 函数中并将其编写到源页面中。

像这样:

function localMain ()
{
    /*--- Put EVERYTHING inside this wrapper, functions and variables.
        Call or use nothing else that's defined in the GM script here.
        Can use objects in the source page's scope, though.
    */
}

//--- Now create the function in the page's scope and run it.
var scriptNode          = document.createElement ("script");
scriptNode.textContent  = localMain.toString() + "\n localMain ();";
document.head.appendChild (scriptNode);

请注意,如果您还将一个库加载到页面的范围中,那么您可能需要localMain()通过使用计时器来延迟运行并检查该库。

于 2010-09-09T18:40:56.167 回答