原理很简单 , 主要是编码思想,需要借鉴, 多多思考
快照沙箱实现 原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模拟js快照沙箱</title>
</head>
<body>
<script>
class SnapshotSandbox {
constructor(window) {
this.proxy = window; //将proxy 赋值为window
this.modifyPropMap = {} // 记录在window上的修改
this.active(); // 默认激活状态
}
// 激活沙箱
active() {
// 声明一个变量用来保存 拍照(给window拍个照也就是保存一下没有改变之前window有哪些私有属性)
this.windowSnapshot = {}
// 循环window上面的属性赋值给windowSnapshot
for (const prop in this.proxy) {
if (this.proxy.hasOwnProperty(prop)) {
this.windowSnapshot[prop] = this.proxy[prop];
}
}
// 将保存的属性添加到上面
Object.keys(this.modifyPropMap).forEach(item => {
this.proxy[item] = this.modifyPropMap[item]
})
}
// 沙箱失活
inactive() {
for (const prop in this.proxy) {
if (this.proxy.hasOwnProperty(prop)) {
// 如果符合这个条件就代表这个属性变化了
if (this.proxy[prop] !== this.windowSnapshot[prop]) {
// 于是就需要将这个属性保存起来
this.modifyPropMap[prop] = this.proxy[prop]
// 将这个变化的属性还原成之前的值
this.proxy[prop] = this.windowSnapshot[prop]
}
}
}
}
}
// 使用
let sandbox = new SnapshotSandbox(window)
; ((window) => {
// 加两个属性
window.a = 1
window.b = 2
console.log(window.a, window.b); // 1,2
sandbox.inactive() // 失去属性
console.log(window.a, window.b); // undefined undefined
sandbox.active() // 还原属性
console.log(window.a, window.b); // 1 ,2
})(sandbox.proxy)
</script>
</body>
</html>
Proxy 代理沙箱 实现 原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>proxy代理沙箱</title>
</head>
<body>
<script>
// 实现Proxy沙箱
class ProxyShaBox {
constructor() {
// 全局属性
const windowSX = window
// 保存这用户更改的属性(变化存储库)
const changeParam = {}
// 个人感觉有点像工厂模式 new 一个 新的proxy实例
this.proxy = new Proxy(changeParam, {
set(tarObj, attr, value) {
tarObj[attr] = value
return true
},
get(tarObj, attr) {
// 如果 变化存储库里面有 就用里面的, 如果没有就用全局的属性
return tarObj[attr] || windowSX[attr]
}
})
}
}
let proxySx1 = new ProxyShaBox()
let proxySx2 = new ProxyShaBox()
; ((window) => {
window.a = 10
console.log(window.a);
})(proxySx1.proxy)
; ((window) => {
window.a = 20
console.log(window.a);
})(proxySx2.proxy)
</script>
</body>
</html>