在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的每个实例定义了一个新的子函数(或类型,如果你愿意)。我想做的是访问父类范围,而不是诉诸于低效率。 像这样:
(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超出了范围。
Child实例(在构造函数中,或在任何类函数中)是否有一种有效的方式来访问父(MyType2)实例?
我知道我可以将Child类定义为一个独立的非嵌套类,然后在ctor中,只需传递Parent实例。但这会创建对父实例的N个引用,每个子实例都有一个引用。这似乎是我想避免的低效率。
感谢任何提示。
编辑 - 我希望Child能够访问父实例的原因是,父拥有一个创建起来相当昂贵的对象 - 类似于数据库连接 - 而且我是就像孩子能够利用那个东西一样。
答案 0 :(得分:3)
如果你在处理javascript时放弃了“类型”,“类”等概念,它可能会帮助你。在javascript中,没有区别于“类型”,“类”,“函数”,“实例”或“对象” - 它一直是“对象”。
由于每个“类型”都是“对象”并且是可变的,因此通过重用单个类型定义,您无法获得从Java或C ++中获得的强类型效率增益。将javascript中的“new”运算符想象为“克隆定义并调用构造函数”,之后仍然可以更改实例的定义。
所以请按照你的第一个工作示例:做一些与众不同的事情,你不会获得任何好处。
答案 1 :(得分:2)
这是我在几个小时后出现的:
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);
通过这种方式,您可以使用Childs实例化所需数量的父母 在下面,每个Child实例都可以访问它的父实例 通过变量父。
答案 2 :(得分:1)
我能想到的唯一方法是将父对象传递给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
的所有实例中都是相同的。
答案 3 :(得分:0)
我没有对此进行测试,但您应该可以使用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);
现在可能存在许多问题,功能性或风格性。但它可以替代其他方法。
答案 4 :(得分:0)
这是一种实现方法。这声明了一个内部对象-这是 kinda ,就像声明一个内部类并立即获取它的实例一样。只需在声明中将对外部类的引用作为对象属性添加即可。
// 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));
}
}