Javascript 让对象回退到另一个对象

发布于 2024-09-01 04:08:06 字数 1182 浏览 5 评论 0原文

这是一段丑陋的 Javascript 代码,如果能找到解决方法就好了。

Javascript 没有类,这是一件好事。但它以一种相当丑陋的方式实现了对象之间的回退。基本构造应该是拥有一个对象,当找不到某个属性时,它会回退到另一个对象。

因此,如果我们希望 a 回退到 b,我们会想要执行以下操作:

a = {sun:1};
b = {dock:2};
a.__fallback__ = b;

then

a.dock == 2;

但是,Javascript 提供了一个 new 运算符和 <代码>原型。所以我们做了远不那么优雅的事情:

function A(sun) {
   this.sun = sun;
};
A.prototype.dock = 2;
a = new A(1);

a.dock == 2;

但除了优雅之外,这严格来说也不太强大,因为这意味着用 A 创建的任何东西都会得到相同后备对象

我想做的是将 Javascript 从这种人为限制中解放出来,并能够为任何单个对象提供任何其他单个对象作为其后备。这样我就可以在有意义时保留当前行为,但在有意义时使用对象级继承。

我最初的方法是创建一个虚拟构造函数:

function setFallback(from_obj, to_obj) {
    from_obj.constructor = function () {};
    from_obj.constructor.prototype = to_obj;
}

a = {sun:1};
b = {dock:2};
setFallback(a, b);

但不幸的是:

a.dock == undefined;

有什么想法为什么这不起作用,或者有任何解决方案来实现 setFallback 吗?

(我通过 node.js 在 V8 上运行,以防这是平台相关的)


编辑:

我在下面发布了一个部分解决方案,该解决方案适用于 V8,但不是不一般。我仍然希望有一个更通用的解决方案。

Here's a ugly bit of Javascript it would be nice to find a workaround.

Javascript has no classes, and that is a good thing. But it implements fallback between objects in a rather ugly way. The foundational construct should be to have one object that, when a property fails to be found, it falls back to another object.

So if we want a to fall back to b we would want to do something like:

a = {sun:1};
b = {dock:2};
a.__fallback__ = b;

then

a.dock == 2;

But, Javascript instead provides a new operator and prototypes. So we do the far less elegant:

function A(sun) {
   this.sun = sun;
};
A.prototype.dock = 2;
a = new A(1);

a.dock == 2;

But aside from elegance, this is also strictly less powerful, because it means that anything created with A gets the same fallback object.

What I would like to do is liberate Javascript from this artificial limitation and have the ability to give any individual object any other individual object as its fallback. That way I could keep the current behavior when it makes sense, but use object-level inheritance when that makes sense.

My initial approach is to create a dummy constructor function:

function setFallback(from_obj, to_obj) {
    from_obj.constructor = function () {};
    from_obj.constructor.prototype = to_obj;
}

a = {sun:1};
b = {dock:2};
setFallback(a, b);

But unfortunately:

a.dock == undefined;

Any ideas why this doesn't work, or any solutions for an implementation of setFallback?

(I'm running on V8, via node.js, in case this is platform dependent)


Edit:

I've posted a partial solution to this below, that works in the case of V8, but isn't general. I'd still appreciate a more general solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

歌枕肩 2024-09-08 04:08:07

好吧,进行更多研究和跨平台检查,还有更多信息(尽管不是通用解决方案)。

有些实现基本上与我为 __fallback__ 所做的一样。它被称为 __proto__ ,几乎是完美的:

a = {sun:1};
b = {dock:2};
a.__proto__ = b;

a.dock == 2;

看起来,当构造一个新对象时发生的事情大致是这样的:

a = new Constructor(...args...);

产生的行为大致相当于:

object.constructor = constructor;
object.__proto__ = constructor.prototype;
constructor.call(this, ...args...);

所以难怪稍后会出现并调整对象的 constructor 或 constructor.prototype 不起作用,因为 __proto__ 设置已经设置。

现在,对于我的 v8 应用程序,我可以只使用 __proto__,但我知道这不会在 IE VM 上公开(我不运行 Windows,所以我无法判断)。所以这不是问题的通用解决方案。

Okay, some more research and cross-platform checking and there's some more information (though not a general solution).

Some implementations have basically what I did for my __fallback__. It is called __proto__ and is about perfect:

a = {sun:1};
b = {dock:2};
a.__proto__ = b;

a.dock == 2;

It seems that, what happens in when a new object is constructed is roughly this:

a = new Constructor(...args...);

produces behavior roughly equivalent to:

object.constructor = constructor;
object.__proto__ = constructor.prototype;
constructor.call(this, ...args...);

So it is no wonder that coming along later and adjusting an object's constructor or constructor.prototype has no effect, because the __proto__ setting is already set.

Now for my v8 application, I can just use __proto__, but I understand it that this isn't exposed on the IE VM (I don't run windows, so I can't tell). So it is not a general solution to the problem.

-柠檬树下少年和吉他 2024-09-08 04:08:06

您可以只使用 Object.create。它是 ES5 的一部分,因此它已经在某些浏览器中本地可用。我相信它完全符合您的要求。

You could just use Object.create. It's part of ES5 so it's already available natively in some browsers. I believe it does exactly what you want.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文