关于grant none/unsafeWindow之疑惑
看官方教程(https://learn.scriptcat.org/%E6%B2%B9%E7%8C%B4%E6%95%99%E7%A8%8B/%E5%85%A5%E9%97%A8%E7%AF%87/grant%E4%BB%8B%E7%BB%8D,none%E4%B8%8EunsafeWindow/)
[沙盒机制的前世今生](https://learn.scriptcat.org/%E6%B2%B9%E7%8C%B4%E6%95%99%E7%A8%8B/%E5%85%A5%E9%97%A8%E7%AF%87/%E6%B2%99%E7%9B%92%E6%9C%BA%E5%88%B6%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F/)
或者网上搜索教程或者问AI
都说的头头是道,感觉似乎懂了,但一测试就懵逼了😳
这里汇总教程的大意是:
1. grant none 是脚本直接运行在前端页面中,此时可以访问页面中的原有变量,可以访问页面元素,但不能访问GM_*系列函数
2. 默认(即无none和unsafeWindow的情况下),运行在沙盒中,无法访问页面中的原有变量,可以访问页面元素,可以访问GM_*系列函数
3. grant unsafeWindow是运行在沙盒中,可以通过unsafeWindow访问页面中的原有变量,可以访问页面元素,可以访问GM_*系列函数
总结如下:
!(data/attachment/forum/202508/14/133355nlmbz306crlg4165.png)
但,我测试下来,却完全不是这样,什么默认,grant none,grant unsafeWindow效果完全一样。
以下是测试代码:
**网页代码如下**
```html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<div id="dom1">dom 1</div>
<button id="closePage">关闭页面</button>
<script>
var a=1;
window.b=2;
c=3;
let d=4;
const e = 5;
</script>
</body>
</html>
```
在线地址 [https://wilson.lovestoblog.com/demo/scriptcat_demo.html](https://wilson.lovestoblog.com/demo/scriptcat_demo.html)
**油猴代码如下**
```js
// ==UserScript==
// @name Demo
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.0
// @descriptiontry to take over the world!
// @author You
// @match *://*/*
// ==/UserScript==
console.log('---> demoooooooooooooooooooo start <---')
console.log('变量', {a,b,c,d,e});
console.log('dom', document.querySelector('#dom1'));
document.querySelector('#closePage').addEventListener('click', ()=>window.close());
console.log('---> demoooooooooooooooooooo end <---')
```
注意,这里div id 是 dom1 不是demo1,别看错了!
**浏览器打印结果**(无论默认,grant none,grant unsafeWindow效果完全一样)
!(data/attachment/forum/202508/14/134415zj758awj7bn8wr8r.png)
所以,**我的疑惑是:我理解错了吗?还是测试错了?还是教程错了?** 懵逼。。。
教程有一些问题,你来听我狡辩一下:
目前的沙盒是一个半沙盒的情况,教程中描述的是全沙盒的情况,教程是我最开始编写的,可能有些问题。
目前的半沙盒是: 沙盒中可以访问外面的变量(除了一些特殊定义的以外:例如`define`、`export`),但是外面的变量不能到沙盒里面来,如果你在沙盒内定义`window.b=100`,在页面上访问b还是为2。
脚本猫最近的一次重构沙盒,里面有很多细节,有兴趣可以看看
https://github.com/scriptscat/scriptcat/pull/524
```js
// ==UserScript==
// @name Demo
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.0
// @descriptiontry to take over the world!
// @author You
// @match *://*/*
// @grant unsafeWindow
// ==/UserScript==
console.log('---> demoooooooooooooooooooo start <---')
console.log('变量', { a, b, c, d, e });
console.log('dom', document.querySelector('#dom1'));
document.querySelector('#closePage').addEventListener('click', () => window.close());
console.log('---> demoooooooooooooooooooo end <---')
a = 2;
b = 3;
c = 4;
d = 5;
// e是常量,不能修改
// e = 6;
console.log(window, this);
window.b = 100;
console.log('变量', { a, b, c, d, e });
``` 我修改了一下教程内容,有什么疑问哥哥可以继续提出,我也好再次进行修改
----
## none和unsafeWindow
简单来说:
`none`就是直接运行在前端页面中,否则就是运行在一个沙盒环境,需要使用`unsafeWindow`去操作前端的元素。
除了`GM_*` 函数外,还有两个特殊的权限,就是`none`和`unsafeWindow`。
默认情况下,你的脚本运行在油猴给你创建的一个半沙盒环境中,在这个沙盒环境中,你可以访问到页面上的元素,但是页面上的元素无法访问到脚本中的内容,用来隔离两个环境。
```js
b = 123;// 脚本中未定义b,会击穿沙盒到页面中去,此时:window.b=undefind,unsafeWindow=123;
console.log(window.b, unsafeWindow.b);
window.b = 234;// 在脚本的window中定义b,后续对b的操作都是在脚本的上下文中进行的,此时:window.b=234,unsafeWindow=123;
console.log(window.b, unsafeWindow.b);
b = 345; // 已经在脚本上下文中定义b了,效果同上,此时:window.b=345,unsafeWindow=123;
console.log(window.b, unsafeWindow.b);
unsafeWindow.b = 456; // 这里操作的是页面的对象,此时:window.b=345,unsafeWindow.b=456;
console.log(window.b, unsafeWindow.b);
``` 本帖最后由 wilsons 于 2025-8-15 11:34 编辑
> 本帖最后由 wilsons 于 2025-8-15 11:32 编辑
> 本帖最后由 wilsons 于 2025-8-15 11:17 编辑
> [王一之 发表于 2025-8-14 15:02](forum.php?mod=redirect&goto=findpost&pid=99547&ptid=9347)
> > 教程有一些问题,你来听我狡辩一下:
目前的沙盒是一个半沙盒的情况,教程中描述的是全沙盒的情况,教 ...
感谢大佬!学习了!
我测试了下,总结如下:
1. 沙盒可以访问页面中的变量。
2. 页面不能访问沙盒中的变量,但隐式全局变量(未声明变量的变量)除外,比如,m=1,这相当于unsafeWindow.m=1,但严格模式下会报错,闭包下也无效。
3. 当油猴脚本grant none 时,window.xxx 可以修改页面中变量的值,此时油猴脚本中unsafeWindow是未定义。
4. 当油猴脚本默认或grant unsafeWindow时,window.xxx 不能修改页面中变量的值,但unsafeWindow.xxx可以修改页面变量的值。
测试代码如下:
页面代码
```html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title></title>
</head>
<body>
<div id="dom1">dom 1</div>
<button id="closePage">关闭页面</button>
<script>
var a=1;
window.b=2;
c=3;
let d=4;
const e = 5;
setTimeout(()=>{
console.log('4秒后页面访问沙盒的变量', { a, b, c, d, e })
console.log('---> demoooooooooooooooooooo end2 <---')
}, 4000)
</script>
</body>
</html>
```
油猴脚本代码
```js
// ==UserScript==
// @name Demo
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.0
// @descriptiontry to take over the world!
// @author You
// @match *://*/*
// ==/UserScript==
console.log('---> demoooooooooooooooooooo start <---')
console.log('变量', {a,b,c,d,e});
console.log('dom', document.querySelector('#dom1'));
document.querySelector('#closePage').addEventListener('click', ()=>window.close());
console.log('---> demoooooooooooooooooooo end <---')
a = 2;
b = 3;
c = 4;
d = 5;
// e是常量,不能修改
// e = 6;
window.b = 100; // @grant none 时生效
unsafeWindow.b = 200; // 默认和@grant unsafeWindow时生效
```
王一之 发表于 2025-8-14 15:23
我修改了一下教程内容,有什么疑问哥哥可以继续提出,我也好再次进行修改
----
感谢大佬!学习了!
我刚才看了教程,感觉有些抽象,新手不容易理解。
我觉得可以像我这个帖子中那样描述,页面中有什么变量,油猴脚本中如何访问,反过来,油猴有哪些变量,页面中如何访问等,这样去描述可能更清晰点。 wilsons 发表于 2025-8-14 15:49
感谢大佬!学习了!
我刚才看了教程,感觉有些抽象,新手不容易理解。
已经更新过去了,有些地方哥哥也可以补充
确实有实例的话,会更好理解一些,但是没那么多精力维护,而且出发角度不同也不会考虑到那么多 王一之 发表于 2025-8-14 15:51
已经更新过去了,有些地方哥哥也可以补充
确实有实例的话,会更好理解一些,但是没那么多精力维护,而且 ...
ok!
大佬辛苦了!
页:
[1]