Javascript 子类访问父类';s闭包变量

Javascript 子类访问父类';s闭包变量,javascript,Javascript,我正在为我当前的项目使用John Resig的继承实现,我想知道是否有一种方法让子类也继承(访问)父类的闭包变量 例如,我编写了以下类 var Foo = (function() { var p = "im p"; var Foo = Class.extend({ getp : function() { return p; } }); return Foo; })(); 现在Foo类可以访问闭包中的变量p。Foo的子类也是 var Ba

我正在为我当前的项目使用John Resig的继承实现,我想知道是否有一种方法让子类也继承(访问)父类的闭包变量

例如,我编写了以下类

var Foo = (function() {  
  var p = "im p";

  var Foo = Class.extend({  
    getp : function() {
       return p;
    }
  });

  return Foo;
})();
现在Foo类可以访问闭包中的变量p。Foo的子类也是

var Bar = Foo.extend({});  
var bar = new Bar;
bar.getp(); // "im p"
这并不奇怪,因为bar.getp只是调用Foo.getp,Foo.getp可以访问p。但是如果我覆盖bar.getp

var Bar = Foo.extend({
  getp : function() {
    return p;
  }
});
现在,当我执行bar.getp()时,它将抛出未定义的p,因为bar无法访问它


我有几种方法可以让p访问bar,但我认为它们有点笨拙,您认为这是实现这一点的最干净的方法。

p
变量仅在自执行匿名
Foo
函数的范围内定义,因此无法检索它

将其视为私有成员,它也仅在声明它的类中可用

如果您只需要检索它-您可以执行以下操作:

var Bar = Foo.extend({
  getp : function() {
    var p = Foo.prototype.getp.call(this);
    return p;
  }
});

p
变量仅在自执行匿名
Foo
函数的范围内定义,因此无法检索该变量

将其视为私有成员,它也仅在声明它的类中可用

如果您只需要检索它-您可以执行以下操作:

var Bar = Foo.extend({
  getp : function() {
    var p = Foo.prototype.getp.call(this);
    return p;
  }
});

闭包范围包括定义函数时范围内的任何内容。在这种情况下,定义第一个
getp
时,
p
在范围内,但定义第二个
getp
时不在范围内。所以你不能引用
p
。事实上,您可能已经发现,第一个
getp
方法引用的
p
实际上对所有
Foo
对象(及其子类)都是通用的

JavaScript实际上不太适合“私有变量”。通常,开发人员在不需要继承时使用闭包范围的变量,或者在需要继承时使用某种约定,例如添加下划线,如下所示:

var Foo = Class.extend({  
    _p : "i'm p",
    getp : function() {
        return this._p;
    }
 });
var Bar = Foo.extend({  
    getpete : function() {
        return Foo.getp() + "ete"; 
        //You can also use this.getp() if you want, there's no difference.
    }
});
然后您可以毫不费力地创建子类:

var Bar = Foo.extend({  
    getp : function() {
        return this._p;
    }
});
现在,我还应该注意到,你的例子非常做作,而且做作的方式有点毫无意义。我的意思是,为什么要用同样返回
p
的东西覆盖
getp()
?如果您的意图是实际创建一个私有的静态属性
p
,那么您所拥有的应该可以正常工作。如果您想访问子类中的
p
,您应该只使用您有权访问的
getp
方法,如下所示:

var Foo = Class.extend({  
    _p : "i'm p",
    getp : function() {
        return this._p;
    }
 });
var Bar = Foo.extend({  
    getpete : function() {
        return Foo.getp() + "ete"; 
        //You can also use this.getp() if you want, there's no difference.
    }
});

希望有帮助

闭包范围包括定义函数时范围内的任何内容。在这种情况下,定义第一个
getp
时,
p
在范围内,但定义第二个
getp
时不在范围内。所以你不能引用
p
。事实上,您可能已经发现,第一个
getp
方法引用的
p
实际上对所有
Foo
对象(及其子类)都是通用的

JavaScript实际上不太适合“私有变量”。通常,开发人员在不需要继承时使用闭包范围的变量,或者在需要继承时使用某种约定,例如添加下划线,如下所示:

var Foo = Class.extend({  
    _p : "i'm p",
    getp : function() {
        return this._p;
    }
 });
var Bar = Foo.extend({  
    getpete : function() {
        return Foo.getp() + "ete"; 
        //You can also use this.getp() if you want, there's no difference.
    }
});
然后您可以毫不费力地创建子类:

var Bar = Foo.extend({  
    getp : function() {
        return this._p;
    }
});
现在,我还应该注意到,你的例子非常做作,而且做作的方式有点毫无意义。我的意思是,为什么要用同样返回
p
的东西覆盖
getp()
?如果您的意图是实际创建一个私有的静态属性
p
,那么您所拥有的应该可以正常工作。如果您想访问子类中的
p
,您应该只使用您有权访问的
getp
方法,如下所示:

var Foo = Class.extend({  
    _p : "i'm p",
    getp : function() {
        return this._p;
    }
 });
var Bar = Foo.extend({  
    getpete : function() {
        return Foo.getp() + "ete"; 
        //You can also use this.getp() if you want, there's no difference.
    }
});

希望有帮助

在javascript中模拟类通常被认为不是最佳的。最好使用它的本机功能以获得最佳效果。@RobG:基于原型的继承中有什么不是本机的?@zerkms您的评论有点混乱,原型在大多数类仿真方案中都有一定程度的使用,否则您基本上只剩下闭包,关键是不要纯粹为了模仿经典继承而使用它们。私有成员、特权方法、super、getter和setter等都可以模拟,但最好是模拟它们的行为,而不是实际的特性(希望有意义)。在javascript中模拟类通常被认为不是最佳的。最好使用它的本机功能以获得最佳效果。@RobG:基于原型的继承中有什么不是本机的?@zerkms您的评论有点混乱,原型在大多数类仿真方案中都有一定程度的使用,否则您基本上只剩下闭包,关键是不要纯粹为了模仿经典继承而使用它们。私有成员、特权方法、super、getter和setter等都可以被模拟,但最好是模拟它们的行为,而不是实际的特性(希望这是有意义的)。实际上,p是我项目中singleton类的实例,我有很多。我想要一种干净的方式在Foo(GameEngine类)及其子类(ClientGameEngine类)中使用它们。最简单的方法是生成那些单例类全局变量,我这样做只是为了避免这种情况。@yngum是的,那么你应该使用我的最后一个示例。在父类中创建必要的getter和setter(您可以在父类中访问闭包范围),但在扩展类时引用它们。您不需要在子类中重新创建
getp
setp
(如果存在的话)。实际上,p是我的项目中singleton类的实例,我有很多。我想要一种干净的方式在Foo(GameEngine类)及其子类(ClientGameEngine类)中使用它们。最简单的方法是让那些单例类的全局,