开发者

Replacement for Prototype.js Class system

We have a set of classes created that depend on Prototype's Class implementation (and some Objec开发者_Python百科t.extend).

The problem is prototype is creating trouble when integrating with the rest of our applications (even with "noconflict" adapters and the such).

Does anybody know of a compatible Class implementation that does not mess with the global scope? Or has anybody been able to "extract" Prototype's to use it alone?


I wrote one a couple of years back (I should go revisit it, and give it a proper name) because I didn't like Prototype's handling of calling methods on the "superclass", which involves creating a function every time an overridden method is called (yes, really). It's very similar to Prototype's except for how you make supercalls; you can readily drop it in and search for super in your code and change it up. My implementation also makes it a bit easier to use named functions rather than anonymous ones, which is useful for many reasons, not least because it helps your tools help you. It also makes private "class" methods trivial. Details below.

But you don't have to use mine. There are other options that will require slightly more work to migrate your code to, but probably not a lot more:

  • John Resig's simple inheritance
  • Dean Edwards' mechanism

My issue with both of them is that they use function decompilation (so does Prototype's Class stuff), and function decompilation (e.g., calling toString on a function) has never been standardized and does not work on some mobile browsers. Resig's mechanism continues to work if function decompilation doesn't work, but it adds overhead to every method in that case (rather than only ones that make supercalls). My mechanism doesn't use function decompilation at all, adds no overhead to method calls, and even makes supercalls highly-efficient.

If you use my mechanism and your Prototype code looks like this:

var SuperThingy = Class.create({
    foo: function(arg) {
        console.log("SuperThingy: " + arg);
        this._pseudoPrivate();
    },
    _pseudoPrivate: function() {
        console.log("I'm not really private.");
    }
});
var Thingy = Class.create(SuperThingy, {
    foo: function(super, arg) {
        console.log("Thingy: " + arg);
        super(arg);
    }
});

You can make minimal changes:

var SuperThingy = Helper.makeClass({
    foo: function(arg) {
        console.log("SuperThingy: " + arg);
        this._pseudoPrivate();
    },
    _pseudoPrivate: function() {
        console.log("I'm not really private.");
    }
});
var Thingy = Helper.makeClass(SuperThingy, {
    foo: function(arg) {
        console.log("Thingy: " + arg);
        this.callSuper(arguments, arg);
    }
});

...or you can make slightly larger changes and get the benefit of a speed increase (callSuper uses arguments.callee, which is slow), properly-named functions (for debugging and such), and truly private functions:

var SuperThingy = Helper.makeClass(function() {
    function SuperThingy_foo(arg) {
        console.log("SuperThingy: " + arg);
        trulyPrivate.call(this);
    }

    function trulyPrivate() {
        console.log("I'm truly private.");
    }

    return {foo: SuperThingy_foo};
});
var Thingy = Helper.makeClass(SuperThingy, function() {
    function Thingy_foo(arg) {
        console.log("Thingy: " + arg);
        foo.$super.call(this, arg);
    }

    return {foo: Thingy_foo};
});


The Prototype source tries to be modular so you can download lang/class.js separately. However a quick glance at the code shows it depends on functions from lang/array.js, lang/object.js, lang/function.js - it would be safer to grab prototype.js and all of the lang directory. That gives you the core of Prototype without the conflicting DOM stuff.

I too find the Class class too useful to do without. I was recommended to try Sugar which is nice but still has no inheritence. It seems the only real alternative currently is MooTools' class.


You should have a look at : MyJS class system

I think you will enjoy !


After trying out ComposeJS, I couldn't find a way to invoke superclass constructors explicitly (they are invoked automatically), so I had to abandon it. I finally settled on JsFace which has many features (inheritance, mixins, static properties, AOP), although a slightly weird syntax to invoke the super class constructor: this.$class.$super.call(args). It also seems to be the fastest implementation, according to its website and also this benchmark, totally blowing away the Resig implementation, which is quite slow. The caveat to watch out for is is that this.$class.$super is always the super class of the final child class, so you may need to do something like this:

var C = Class(A, {
  constructor: function (x) {
    C.$super.call(this, x);
  },
  ...
}

instead of

var C = Class(A, {
  constructor: function (x) {
    this.$class.$super.call(this, x);
  },
  ...
}

which is like the examples, if you have multiple levels of inheritance, otherwise you'll get an infinite recursion.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜