【问题标题】:Javascript, inner classes, and how to access parent scope efficientlyJavascript、内部类以及如何有效地访问父作用域
【发布时间】:2011-06-13 16:56:36
【问题描述】:

在 Javascript 中,我想定义一个具有内部(或嵌套)类的类。在内部类中,我希望能够访问父实例。我怎样才能有效地做到这一点?

一些代码会显示我的意思。假设我定义了一个类 MyType1,它公开了几个属性和一个函数SayHello

(function(){
    MyType1 = function(name){
        this.TypeName = "MyType1";
        this.Name = name;
    };

    MyType1.prototype.SayHello = function() {
        say(this.Name + " says hello...");
    };
})();

好的,现在,从那里开始,我想在 MyType1 中添加一个“内部类”,所以我添加了一些新代码,使其看起来像这样:

(function(){
    MyType1 = function(name){
        this.TypeName = "MyType1";
        this.Name = name;
        var parentName = name;
        this.Child = function(name) {
            this.Description = parentName + "'s child, " + name;
        };

        this.Child.prototype.Introduce = function() {
            say(this.Description + ", greets you...");
        };
    };

    MyType1.prototype.SayHello = function() {
        say(this.Name + " says hello...");
    };
})();

现在我可以像这样使用这些类:

var x = new MyType1("Victor");
x.SayHello();

var c = new x.Child("Elizabeth");
c.Introduce();

一切正常。但它为 MyType1 的每个实例定义了一个新的 Child 函数(或 type,如果你愿意的话)。我想做的是访问父类范围,而不是利用这种低效率。 像这样的:

(function(){
    MyType2 = function(name){
        this.TypeName = "MyType2";
        this.Name = name;
        this.Prop1 = 1872;
        var parentName = name;
    };

    MyType2.prototype.SayHello = function() {
        say(this.Name + " says hello...");
    };

    var c1 = function(name) {
        this.Description = parentName + "'s child, " + name;
        //                ^^ no go! ^^
    };

    c1.prototype.Introduce = function() {
        say(this.Description + ", greets you...");
    };

    MyType2.prototype.Child = c1;

})();

但是,这不起作用。当然,parentName 变量超出了范围。

子实例(在构造函数中,或在任何类函数中)是否有有效的方法来访问父 (MyType2) 实例?


我知道我可以将 Child 类定义为一个独立的非嵌套类,然后在 ctor 中,只需传递 Parent 实例。但这会创建 N 个对父实例的引用,每个子实例一个。这似乎是我想避免的低效率。

感谢任何提示。


EDIT - 我希望 Child 能够访问父实例的原因是,父实例拥有一个创建起来相当昂贵的对象 - 类似于 db 连接 - 我会喜欢孩子能够利用那个东西。

【问题讨论】:

  • 呃,还有更多滥用 Javascript 来引入“OOP”的废话。这种语言没有类:如果你想要它们,请使用有类的东西!
  • 您可能会发现这很有用:blog.niftysnippets.org/2009/09/… 这是一组帮助函数(及其解释),提供了一种简单但有效的方法来创建通过原型继承创建的“类”的“子类” .看起来你是手动完成的,所以它可能会为你省点麻烦。
  • @Tomalek:你说的很对,当然,JavaScript 没有类。它是面向对象的,但确实具有继承性。
  • @Crowder :我没有进行原型继承。这是一个嵌套/内部类。此示例中没有继承。 @Vidas - anon fn 仅用于在我的代码模块中确定范围帮助。它没有为示例添加任何内容。 @Tomalak - 听起来你对我用 my 代码做什么有疑问。嗯。有没有想过为此去看治疗师?
  • @LightnessRacesinOrbit 这样的可憎? developer.mozilla.org/en-US/docs/Web/JavaScript/…

标签: javascript oop closures


【解决方案1】:

这是一种方法。这声明了一个内部对象 - 有点 就像声明一个内部类并立即获取它的一个实例。对外部类的引用只是作为对象属性添加到声明中。

// ES6 - example of an inner object.
class DancingFoo {
    constructor(radio) {
        this._radioListener = { 
            outer: this,
            onIsPlaying()      { this.outer._dancing = true; },
            onStoppedPlaying() { this.outer._dancing = false; }
        }
        radio.attachListener(this._radioListener);
    }
}

或者如果你想要一个内部类,你可以创建稍后的实例......

// ES6 inner class example    
class DancingFoo {
    constructor(radio) {
        let RadioListener = class { 
            constructor(outer) { this.outer = outer; }
            onIsPlaying()      { this.outer._dancing = true; }
            onStoppedPlaying() { this.outer._dancing = false; }
        }
        radio.attachListener(new RadioListener(this));
    }
}

【讨论】:

    【解决方案2】:

    我尚未对此进行测试,但您应该可以为此使用 JSON:

    //code here
    var number = {
        real : {
            value : 0, //default value
            rational : {
                integer : {
                    isNegative : false,
                    value : 0 //default value
                }
            }
        },
        imaginary : {
            //code
        }
    };
    
    var number2 = Object.create(number.rational.integer.prototype);
    

    现在可能存在很多问题,无论是功能上的还是风格上的。但它是此处发布的其他方法的替代方法。

    【讨论】:

      【解决方案3】:

      这是我几个小时后想出的:

      var Parent = function() {
        this.name = "Parent";
      
        this.Child = Child;
        this.Child.prototype.parent = this;
      }
      
      var Child = function() {
      
      }
      
      var parent = new Parent();
      var child = new parent.Child();
      
      console.log(child.parent.name);
      

      通过这种方式,您可以实例化任意数量的父母,以及他们的孩子 在下面,每个子实例都可以访问它的父实例 通过变量parent

      【讨论】:

        【解决方案4】:

        如果您在处理 javascript 时摒弃“类型”、“类”等概念,它可能会对您有所帮助。在 javascript 中,与“类型”、“类”、“函数”、“实例”或“对象”没有区别——它一直是“对象”。

        由于每个“类型”都是一个“对象”并且是可变的,因此您无法通过重用单个类型定义从 Java 或 C++ 中获得强类型的效率提升。将 javascript 中的“new”运算符想象为“克隆定义并调用构造函数”之类的东西,之后仍然可以更改实例的定义。

        因此,请使用您的第一个有效示例:做不同的事情不会获得任何收益。

        【讨论】:

          【解决方案5】:

          我能想到的唯一方法是将父对象传递给 Child 构造函数:

          MyType2.Child = function (parent, name) {
              this.parent = parent;
              this.name = name;
              this.Description = this.parent.name + "'s child, " + name;
          };
          

          并用以下方式实例化它:

          var x = new MyType2("Victor");
          
          var c = new MyType2.Child(x, "Elizabeth");
          

          我的理由是Child 构造函数是MyType2 的“静态”属性而不是您的示例中的实例化对象x 更有意义,因为我们正在谈论类型 在这里,它们在 MyType2 的所有实例中都是相同的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-22
            • 2013-08-21
            • 2011-09-10
            相关资源
            最近更新 更多