Javascript、内部类以及如何有效地访问父范围

Javascript、内部类以及如何有效地访问父范围,javascript,oop,closures,Javascript,Oop,Closures,在Javascript中,我想用一个内部(或嵌套)类定义一个类。在内部类中,我希望能够访问父实例。我怎样才能有效地做到这一点 一些代码将显示我的意思。假设我定义了一个类MyType1,它公开了几个属性和一个函数,SayHello: (function(){ MyType1 = function(name){ this.TypeName = "MyType1"; this.Name = name; }; MyType1.prototype.

在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();
(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;

})();
现在我可以像这样使用这些类:

(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();
(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;

})();

这一切都有效。但是它为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();
(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
var超出了范围

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


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

谢谢你的提示



编辑-我希望孩子能够访问父实例的原因是,父实例拥有一个创建成本相当高的对象—比如db连接—我希望孩子能够利用这个东西

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

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实例中都是相同的,如果在处理javascript时去掉“类型”、“类”等概念,可能会对您有所帮助。在javascript中,与“类型”、“类”、“函数”、“实例”或“对象”没有区别——它一直是“对象”

因为每个“类型”都是“对象”,而且是可变的,所以您不会从java或C++中获得重用的类型类型的效率增益。将javascript中的“new”操作符想象成“克隆定义并调用构造函数”,之后实例的定义仍然可以更改


因此,请继续你的第一个工作示例:做一些不同的事情不会有任何收获。

这是我在几个小时后得出的结论:

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

我还没有对此进行测试,但您应该能够使用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);

现在可能会有很多问题,功能或风格。但这是一种不同于此处发布的其他方法的替代方法。

这是一种方法。这声明了一个内部对象,类似于声明一个内部类并立即获得它的实例。对外部类的引用只是作为声明中的对象属性添加

// 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));
    }
}

呃,还有更多的Javascript滥用,带来了“OOP”的废话。这种语言没有类:如果你想要它们,就使用它!您可能会发现这很有用:它是一组帮助函数(及其解释),提供了一种简单但高效的方法来创建通过原型继承创建的“类”的“子类”。看起来您是相当手工地完成的,所以这可能会为您节省一些麻烦。@Tomalek:您说得很对,当然,JavaScript没有类。它是面向对象的,而且确实有继承性。@Crowder:我不是在做原型继承。它是一个嵌套/内部类。本例中没有继承@Vidas-anon fn仅用于我的代码模块中的作用域帮助。它对这个例子没有任何补充@Tomalak-听起来你对我的代码做了些什么有点犹豫。嗯,你有没有想过去看心理医生?@LightnessRacesinOrbit,像这样讨厌的事情?