当前位置: 首页 > news >正文

前端作用域冲突之快照沙箱和代理沙箱

关于快照沙箱和代理沙箱的使用时机并没有具体明确的指导原则,它们的使用一般需要根据具体的使用背景和应用需求来决定。一般来说,快照沙箱在应用初始运行时捕获并记录其对全局变量的改动,之后在应用卸载时回退这些改动,保证不会对其他环境和应用产生影响。而代理沙箱则是利用JS的Proxy对象在应用运行时动态地隔离其全局变量操作,代理沙箱可以处理应用的动态脚本并实现一些无法通过静态分析完成的全局变量隔离操作。

快照沙箱的实现方式相对简单且易于理解,它提供了对低版本浏览器的良好支持。但使用快照沙箱可能会存在一定的内存开销,并且对应用的动态脚本处理能力有限。

而代理沙箱虽然在处理动态脚本和全局变量隔离方面有优势,但要注意的是,代理沙箱的实现依赖于JavaScript的Proxy对象,这意味着在某些不支持Proxy的低版本浏览器中,代理沙箱无法正常工作。

所以,如果你的应用需要处理大量的动态脚本,并且环境支持Proxy,那么使用代理沙箱可能会是一个好选择。相反,如果应用主要由静态脚本构成,或者需要在低版本浏览器中运行,那么快照沙箱可能更适合你的需求。

  1. 代理沙箱

代理沙箱是通过代理API创建一个全局对象的替代者,并通过它来控制对全局对象的访问。主要使用了Proxy对象来创建代理,Proxy对象的作用是,在对象之间创建一个代理,该代理可以监视并修改对原始对象的访问。

// 原始全局对象
const globalContext = window;
// 创建 target 对象
const target = Object.create(null);
// 创建代理
const proxy = new Proxy(target, {get: (target, p) => {// hijack global accessingif (p === 'window' || p === 'self' || p === 'globalThis') {return proxy;}// 返回原始全局对象的属性值return globalContext[p];},set: (target, p, value) => {// 修改代理对象的属性值,不影响原始全局对象target[p] = value;return true;}
});

在这段代码中,通过代理控制访问到全局对象的所有操作。例如:

当试图获取 globalContext 上的某个属性时(例如,globalContext.window),将返回被代理的对象(代理沙箱);
当试图设置 globalContext 上的某个属性时,它将修改并返回代理对象,保持全局对象不变。

  1. 快照沙箱

快照沙箱主要思路是,一开始就拍摄全局状态的快照,然后在代码执行过程中任何对全局状态的修改只会影响当前沙箱环境,不会泄露到全局环境。

// 创建代理对象
class SnapshotSandbox {constructor() {// 保存环境快照this.snapshot = this.recordSnapshot();}// 记录全局状态快照recordSnapshot() {return new Map(Object.getOwnPropertyNames(window).map(name => [name, window[name]]));}// 通过快照还原全局状态restoreSnapshot() {for (const [name, value] of this.snapshot.entries()) {if (!(value === window[name])) {window[name] = value;}}}
}

在代码中,我们首先创建一个类SnapshotSandbox。在构造函数中,我们记录了window对象初始状态的快照。

记录快照的方法是通过Object.getOwnPropertyNames(window)得到全局对象上所有自有属性的键,然后每个键和对应的初始值一起保存在 Map 中。

当我们受够了在沙箱环境中的修改后,可以通过调用restoreSnapshot()方法把全局环境恢复到初始状态,也就是我们保存的全局环境快照。
以上就是文章全部内容了,如果喜欢这篇文章的话,还希望三连支持一下,感谢!

相关文章:

  • leetcode:最近的请求次数
  • Vue可视化表单设计 FcDesigner v3.1.0 发布,新增 12 个组件,支持事件配置等
  • Java项目:96 springboot精品在线试题库系统
  • preventDefault()与stopPropagation()有什么区别?
  • IGraph使用实例——线性代数计算(blas)
  • 强达电路营收下滑净利润急剧放缓:周转率骤降,2次因环保被罚
  • 初识SDN(二)
  • 弘君资本:存储芯片概念强势,西测测试三连板,佰维存储涨超10%
  • 【C++】6-6 你好,输出的格式控制(对齐)
  • H6911 DC2.6-40V升压IC 升24V36V48V60V80V100V10A数转模无频闪LED芯片
  • 过滤器、监听器、拦截器的区别
  • 格式化数据恢复指南:从备份到实战,3个技巧一网打尽
  • pycharm 上一次编辑位置不见了
  • AI时代下的智能商品计划管理
  • Love-Yi情侣网站3.0存在SQL注入漏洞
  • [译]Python中的类属性与实例属性的区别
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • MaxCompute访问TableStore(OTS) 数据
  • mysql中InnoDB引擎中页的概念
  • React Native移动开发实战-3-实现页面间的数据传递
  • vue的全局变量和全局拦截请求器
  • Xmanager 远程桌面 CentOS 7
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 从输入URL到页面加载发生了什么
  • - 概述 - 《设计模式(极简c++版)》
  • 关于使用markdown的方法(引自CSDN教程)
  • 前端面试总结(at, md)
  • 微信支付JSAPI,实测!终极方案
  • 一份游戏开发学习路线
  • FaaS 的简单实践
  • 仓管云——企业云erp功能有哪些?
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (C语言)逆序输出字符串
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (定时器/计数器)中断系统(详解与使用)
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (黑马C++)L06 重载与继承
  • (回溯) LeetCode 77. 组合
  • (每日一问)设计模式:设计模式的原则与分类——如何提升代码质量?
  • (转)程序员技术练级攻略
  • (转)程序员疫苗:代码注入
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .net core docker部署教程和细节问题
  • .NET Core 中的路径问题
  • .NET MAUI Sqlite程序应用-数据库配置(一)
  • .NET Standard 支持的 .NET Framework 和 .NET Core
  • .NET 直连SAP HANA数据库
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .net开发日常笔记(持续更新)