身份保护膜代理的用例是什么?

问题描述 投票:0回答:1

当我阅读有关 ES6 代理的内容时,它似乎很容易理解,直到我查看了这个示例

我被难住了。我不明白他们使用的“湿/干”术语,而且我不知道什么时候我会遇到这种情况,这将是理想的选择,特别是因为我似乎找不到一个。

有人可以简短解释一下什么情况下会发生这种情况吗?

javascript metaprogramming es6-proxy
1个回答
7
投票

首先,了解一些基础知识:对象是属性的集合(其中一些是函数,正式名称为“方法”)。 这听起来似乎很明显,但很重要:您可以通过对象和属性名称引用其他值。

代理允许您重写通过(包含)对象的元组和属性名称引用其他值的规则。 例如,您可以将“私有”成员隐藏在代理后面。

但是假设您有一个循环对象引用。 例如,

var x = { z: function() { throw new Error("This shouldn't be callable"); };
var X = /* proxy representing x, where X.z is hidden and cannot be called */;

var y = { x: x };
x.y = y;

或者用文档对象模型术语来说,document.documentElement.ownerDocument == document。

在普通代理中,引用 X.y 将返回 y。 没有什么真正的问题......除了 X.y.x === x 和 X.y.x !== X。所以我仍然可以打电话:

X.y.x.z(); // throws new Error("This shouldn't be callable")

膜就是为了确保非原始属性(对象和函数)保留这种身份关系,并通过属性查找的任意组合维护您所拥有的任何代理规则。 膜可以防止您意外地直接访问各种对象的底层(可能是本机)实现。

如果 X 是 x 的基于膜的代理,X.y 将不会返回 y。 相反,它会返回 y 的代理,我将其称为 Y。Y 公开 y 的属性,就像 X 公开 x 的属性一样。

更重要的是,假设我指的是 X.y.x:

X.y.x === X; // true
X.y.x !== x; // also true
typeof X.y.x.z // returns "undefined", not "function"
X.y.x.z(); // throws TypeError("X.y.x.z is not a function")

对 X 的引用(x 的代理)通过膜返回。 因此,身份属性被保留。 (x.y.x === x,所以 X.y.x === X。)

这是最重要的概念:膜意味着你可能永远看不到原始对象,只能看到代表它们的代理对象。

var X = (function() {
    var x = { z: function() { throw new Error("This shouldn't be callable"); };
    var y = { x: x };
    x.y = y;

    var X = /* membrane proxy representing x, where X.z is hidden and cannot be called */;
    return X;
})();

X.y.x === X; // still true

Tom van Cutsem 关于 JavaScript 膜的文章(您在上面引用了其中一篇文章)中,值 x、y 和 x.z 都可以被视为“湿”对象图的一部分,而通过 X 或 Y 引用的任何内容将是“干”对象图的一部分。 (这里的术语“图”来自图论,它是离散数学研究的一部分。对象图意味着一组相关的对象,而膜是将“本机”对象集与这些对象的代理集分开的东西。 )

x 和 y 值无法直接从函数外部访问。 (用 JavaScript 的说法,在这个例子中它们是局部变量,但是从膜的角度来看,这在一定程度上具有误导性:如果我们谈论 DOM 文档,那么您在像 Mozilla Firefox 这样的 Web 浏览器中真正得到的是DOM 文档,而不是本机内存中的实际文档对象。无论是本地变量还是插入到您正在运行的 JavaScript 范围中的值,膜及其代理都不会关心。)

相反,您对 x、y 及其属性的唯一访问是通过 X 膜代理以及从 X 获得的任何属性。因为它是膜,所以该访问始终是间接的。

对于发生这种情况的场景:假设您拥有可以执行各种操作的受信任代码,例如访问计算机的文件系统。 您不希望网页能够直接从文件系统读取,或更糟糕的是,写入文件系统。 代理膜仅公开您打算公开的属性和方法,从而减少了网页可以使用的 API,从而大大降低了意外访问受信任代码的可能性。 这使得安全漏洞变得更加罕见。

最重要的是,如果膜实现正确(这比听起来要困难得多),

网页 JavaScript 不知道也不关心它正在处理代理。

网页脚本认为它正在处理普通的 DOM。 这就是我们想要的。

© www.soinside.com 2019 - 2024. All rights reserved.