javascript - 身份保持膜代理的用例是什么?

标签 javascript metaprogramming es6-proxy

当我阅读有关 ES6 代理的内容时,它似乎很容易理解,直到我看了 this example。 .

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

有人可以简要说明这种情况会发生在哪种情况下吗?

最佳答案

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

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

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

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")

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

如果 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's articles on JavaScript Membranes ,其中一个你cited above ,值 x、y 和 x.z 都可以被视为“湿”对象图的一部分,而通过 X 或 Y 引用的任何内容都将是“干”对象图的一部分。 (这里的术语图来自图论,它是离散数学研究的一部分。对象图是指一组相关的对象,而膜是将“ native ”对象集与这些对象的代理集分开的东西。 )

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

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

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

最重要的是,如果膜实现是正确的(这比听起来要难得多),网页 JavaScript 不知道或不关心它正在处理代理。网页脚本认为它是处理一个普通的 DOM。这就是我们想要的。

关于javascript - 身份保持膜代理的用例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36368363/

相关文章:

javascript - 将事件类添加到多个切换类

javascript - 类型错误 : IPFS is not a constructor

javascript - 选择没有某些后代的元素内容

ruby-on-rails - 涉及 has_many & belongs_to 关联的元编程问题

ruby - 如何调用在不同上下文中获取 block 的 Proc?

ruby 类扩展

javascript - 使用 ES6 Proxy 懒加载资源

JavaScript 代理目标对象与属性描述符冲突

javascript - 从 JSON 对象检索新数据不起作用?

javascript - Promise 作为类方法调用触发 object.then 解析