开发者

Javascript Getting Objects to Fallback to One Another

开发者 https://www.devze.com 2022-12-30 00:24 出处:网络
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 found

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 开发者_C百科= 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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号