在javascript中模拟超级 [英] Emulate super in javascript

查看:102
本文介绍了在javascript中模拟超级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上有一个很好的优雅机制来模拟 super ,其语法与以下之一一样简单

Basically is there a good elegant mechanism to emulate super with syntax that is as simple as one of the following


  • this。$ super.prop()

  • this。$ super.prop.apply(this,arguments);

  • this.$super.prop()
  • this.$super.prop.apply(this, arguments);

坚持的标准是:


  1. 这个。$ super 必须是对原型的引用。即如果我在运行时更改超级原型,则会反映此更改。这基本上意味着父母有一个新的属性然后这应该在运行时通过 super 显示在所有孩子的运行时,就像对父母的硬编码引用会反映更改

  2. this。$ super.f.apply(this,arguments); 必须适用于递归调用。对于任何链接的继承集,其中在继承链上进行多次超级调用时,您不能点击递归问题。

  3. 您不能硬编码对子项中超级对象的引用。即 Base.prototype.f.apply(this,arguments); 打败了这一点。

  4. 你不能使用X to JavaScript编译器或者JavaScript预处理器。

  5. 必须符合ES5

  1. this.$super must be a reference to the prototype. i.e. if I change the super prototype at run-time this change will be reflected. This basically means it the parent has a new property then this should be shown at run-time on all children through super just like a hard coded reference to the parent would reflect changes
  2. this.$super.f.apply(this, arguments); must work for recursive calls. For any chained set of inheritance where multiple super calls are made as you go up the inheritance chain, you must not hit the recursive problem.
  3. You must not hardcode references to super objects in your children. I.e. Base.prototype.f.apply(this, arguments); defeats the point.
  4. You must not use a X to JavaScript compiler or JavaScript preprocessor.
  5. Must be ES5 compliant

天真的实现将是这样的。

The naive implementation would be something like this.

var injectSuper = function (parent, child) {
  child.prototype.$super = parent.prototype;
};

但这打破条件2

我见过的最优雅的机制是 IvoWetzel的 eval hack ,这几乎是一个JavaScript预处理器因此没有标准4。

The most elegant mechanism I've seen to date is IvoWetzel's eval hack, which is pretty much a JavaScript preprocessor and thus fails criteria 4.

推荐答案

我认为没有免费的方式你提到的递归超级问题。

我们不能搞砸这个因为这样做会阻止我们以非标准的方式改变原型,或者让我们向上移动原型链,失去实例变量。因此,当我们进行超级操作时,必须知道当前类和超类,而不将该责任传递给或其中一个属性。

We can't mess with the this because doing so would either force us to change prototypes in a nonstandard way, or move us up the proto chain, losing instance variables. Therefore the "current class" and "super class" must be known when we do the super-ing, without passing that responsibility to this or one of its properties.

我们可以尝试做很多事情,但我认为只会产生一些不良后果:

There are many some things we could try doing but all I can think have some undesireable consequences:


  • 在创建时向函数添加超级信息,使用arguments.calee或类似的邪恶访问它。

  • 调用super方法时添加额外信息

  • Add super info to the functions at creation time, access it using arguments.calee or similar evilness.
  • Add extra info when calling the super method

$super(CurrentClass).method.call(this, 1,2,3)

这迫使我们复制当前的类名(所以我们可以在一些超级字典中查找它的超类)但至少它没有那么糟糕复制超类名称,(因为与继承关系耦合,如果更糟,那么内部耦合与类'自己的名称)

This forces us to duplicate the current class name (so we can look up its superclass in some super dictionary) but at least it isn't as bad as having to duplicate the superclass name, (since coupling against the inheritance relationships if worse then the inner coupling with a class' own name)

//Normal Javascript needs the superclass name
SuperClass.prototype.method.call(this, 1,2,3);

虽然这远非理想,但 2.x Python 。 (他们固定超级3.0以便它不再需要参数,但我不确定涉及多少魔法以及它对JS的可移植性如何)

While this is far from ideal, there is at least some historical precedent from 2.x Python. (They "fixed" super for 3.0 so it doesn't require arguments anymore, but I am not sure how much magic that involved and how portable it would be to JS)

编辑:工作小提琴

var superPairs = [];
// An association list of baseClass -> parentClass

var injectSuper = function (parent, child) {
    superPairs.push({
        parent: parent,
        child: child
    });
};

function $super(baseClass, obj){
    for(var i=0; i < superPairs.length; i++){
        var p = superPairs[i];
        if(p.child === baseClass){
            return p.parent;
        }
    }
}

这篇关于在javascript中模拟超级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆