关于javascript:从Greasemonkey访问变量到Page&

Accessing Variables from Greasemonkey to Page & vice versa

我在test.js中有以下代码,它在前面运行:

1
2
alert('stovetop');
alert(greasy);

我在test.user.js中有以下代码:

1
2
3
4
5
6
7
(function () {

    'use strict';
    var greasy = 'greasy variable';
    document.title = 'greasy title';

}());

"StoveTop"会收到警报,因此我知道页面javascript可以工作,而document.title会得到更改,因此我知道脚本javascript可以工作。但是,在网页上我得到了错误:

Error: ReferenceError: greasy is not defined Source File: /test.js

如何从网页访问greasemonkey设置的变量,反之亦然?


  • GreaseMonkey脚本在单独的范围内运行,也可以在沙盒中运行,具体取决于@grant设置。

  • 此外,问题代码将greasy隔离在一个函数范围内(如gladoscc所说)。

  • 最后,在默认情况下,test.js将在greasemonkey脚本启动之前启动,因此无论如何它都不会看到任何设置变量。用@run-at document-start来解决这个问题。

因此,根据test.js,在之前运行:

1
2
3
4
window.targetPages_GlobalVar = 'stovetop';

console.log ("On target page, local global:", targetPages_GlobalVar);
console.log ("On target page, script global:", gmScripts_GlobalVar);

然后,以下内容将起作用:

无沙盒:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// ==UserScript==
// @name        _Greasemonkey and target page, variable interaction
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @include     http://jsbin.com/esikut/*
// @run-at      document-start
// @grant       none
// ==/UserScript==

//--- For @grant none, could also use window. instead of unsafeWindow.
unsafeWindow.gmScripts_GlobalVar = 'greasy';

console.log ("In GM script, local global:", unsafeWindow.targetPages_GlobalVar);
console.log ("In GM script, script global:", gmScripts_GlobalVar);

window.addEventListener ("DOMContentLoaded", function() {
    console.log ("In GM script, local global, after ready:", unsafeWindow.targetPages_GlobalVar);
}, false);

带沙盒,无功能范围,unsafeWindow:==>重要更新:GreaseMonkey更改了2.0版的unsafewindow处理,下一个示例脚本将无法与gm 2.0或更高版本一起使用。另外两个解决方案仍然有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// ==UserScript==
// @name        _Greasemonkey and target page, variable interaction
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @include     http://jsbin.com/esikut/*
// @run-at      document-start
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/


unsafeWindow.gmScripts_GlobalVar = 'greasy';

console.log ("In GM script, local global:", unsafeWindow.targetPages_GlobalVar);
console.log ("In GM script, script global:", unsafeWindow.gmScripts_GlobalVar);

window.addEventListener ("DOMContentLoaded", function() {
    console.log ("In GM script, local global, after ready:", unsafeWindow.targetPages_GlobalVar);
}, false);

使用沙盒,没有函数范围,脚本注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// ==UserScript==
// @name        _Greasemonkey and target page, variable interaction
// @include     http://YOUR_SERVER.COM/YOUR_PATH/*
// @include     http://jsbin.com/esikut/*
// @run-at      document-start
// @grant       GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/


function GM_main () {
    window.gmScripts_GlobalVar = 'greasy';

    console.log ("In GM script, local global:", window.targetPages_GlobalVar);
    console.log ("In GM script, script global:", window.gmScripts_GlobalVar);

    window.addEventListener ("DOMContentLoaded", function() {
        console.log ("In GM script, local global, after ready:", window.targetPages_GlobalVar);
    }, false);
}

addJS_Node (null, null, GM_main);

function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    scriptNode.type                         ="text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}

笔记:

  • 您可以在此页面(jsbin.com/esikut)上测试这些脚本。
  • 没有沙箱,unsafeWindowwindow是一样的。
  • 所有这些脚本在控制台上生成相同的输出:

    1
    2
    3
    4
    5
    In GM script, local global: undefined
    In GM script, script global: greasy
    On target page, local global: stovetop
    On target page, script global: greasy
    In GM script, local global, after ready: stovetop
  • 除了火狐,脚本注入代码还可以在多种浏览器中使用。unsafeWindow目前只在firefox+greasemonkey(或scriptish)或chrome+tampermonkey中工作。


  • 您的变量greasy是在匿名函数的范围内定义的。即使在用户脚本中,也不能访问greasy,除非它是您的函数的一部分。例子:

    1
    2
    3
    4
    5
    (function(){
        var foo = 5;
        alert(foo);
    }();
    alert(foo); //ERROR, because foo is undefined outside of the function.

    这样做:

    1
    2
    3
    4
    5
    var foo = 5;
    (function(){
         alert(foo);
    }();
    alert(foo);

    另外,为什么要将所有代码放在匿名函数中,然后执行它?


    您还可以使用localstorage:

    1
    2
    3
    localStorage.setItem("numberOfThings","42");

    localStorage.getItem("numberOfThings");