【问题标题】:JavaScript prototype chaining with simple handling of this using 'self'JavaScript 原型链,使用 'self' 进行简单处理
【发布时间】:2012-05-07 21:32:11
【问题描述】:

我开始喜欢下面的模式(抱歉,这里是 Coffeescript,因为在这种情况下它更具可读性):

Parent = (proto)->
  self = Object.create proto
  public1 = ->
    console.log "in public1 with self: ", self
    console.log "in public1 with name: ", self.name

  self.public1 = public1
  self

Child = (proto)->
  self = new Parent proto

  private1 = ->
    console.log "in private1 with self: ", self
    console.log "in private1 with name: ", self.name
    self.public1()

  public2 = ->
    console.log "in public2 with self: ", self
    console.log "in public2 with name: ", self.name
    private1()

  self.public2 = public2
  self

GrandChild = (proto)->
  self = new Child proto

  public3 = ->
    console.log "in public3 with self", self
    console.log "in public3 with name: ", self.name
    self.public2()

  self.public3 = public3
  self

felix = new GrandChild name: "Felix"
felix.public2()

这种简单的多重继承尝试可行,并且可以简单且明显方便地使用“自我”……当您像我一样来自其他 oop 语言时,这很聪明。

问题:每个 GrandChild 对象都会创建一个 NEW Child 以及一个 NEW Parent 对象,因此如果创建了许多 GrandChild 对象,内存消耗就会增加。

据我所知,用 Child 和 Parent 的方法增加 GrandChild 的原型只会在 GrandChild 对象中引用他们的方法(并节省大量空间),但是向上和向下阅读我找不到访问 self 的方法上面的解决方案。

我知道 Coffeescript 本身在 JS 的原型继承之上提供了一个基于类的继承系统。其他库也提供解决方案。我想简单地了解如何根据用例选择正确的解决方案。

如果 - 例如 - 我想将 Child 的 private1 和 public2 放入原型中,以便引用而不是复制这些函数,该怎么办?

那时有人可以启发我吗?

【问题讨论】:

  • 我会帮助你,但我发现 Coffescript 实际上很难阅读,很难分辨什么是参数或函数应该在哪里结束。
  • 这个多重继承如何?我只看到一个长的(单一的)继承链。
  • @GGG:纠正我,但我可以在 felix 上调用 public1,而不能在 Parent 实例上调用 public2。 AFAIK 这应该是多重继承。你的意思是多态继承——实际上这种方法没有提供什么?
  • @GeorgieF 对我来说它看起来像是单一继承。多重继承就像Werewolf extends Human, Wolf

标签: javascript inheritance coffeescript prototype


【解决方案1】:

问题:每个 GrandChild 对象都会创建一个 NEW Child 以及一个 NEW 父对象,这样内存消耗会在很多情况下增长 已创建 GrandChild 对象。

错误。你在这里所做的,比如当你new GrandChild 时,你实例化了一个Parent,然后用Child 构造函数中的方法装饰它,然后再从GrandChild 构造函数中装饰它。这是同一个对象,从Object.create proto 一直到孙子。在这方面,你根本不会用虚拟对象乱扔你的上下文。

用 Child 和 Parent 的方法增加 GrandChild 的原型 就我而言,只会在 GrandChild 对象中引用他们的方法 理解(并节省大量空间),但上下阅读我不 找到一种访问自我的方法,就像我使用鞋面的方式一样 解决方案。

基于闭包的私有方法和原型通常无法相处。当你在这样的构造函数中做这一切时,你可以有很大的灵活性,但你会失去使用原型的优势(比如在新范围内不重新定义函数的速度)。

我知道 Coffeescript 本身提供了一个基于类的继承系统 在 JS 的原型继承之上。其他库提供的解决方案为 好。我想简单地了解选择正确的方法 解决方案取决于用例。

确实如此,并且在使用咖啡脚本时没有理由不使用它。有很多想法。但是私有方法同样会很棘手。通常私有方法只是简单地公开,但下划线前缀Foo.prototype._privateMethod 表示它们的私有性。如果这还不够好,事情就会开始变得时髦。

如果——例如——我想把 private1 和 public2 的 Child变成一个原型,让这些函数被引用而不是 复制的?

公共方法可以进入原型并很好地传播,私有方法不多。 Private 根本不是考虑 javascript 中事物的好方法,因为它不像其他语言那样受支持。相反,您有权访问的任何值(包括函数)要么通过局部变量或闭包在当前范围内,要么是通过局部变量或闭包在当前范围内的对象的属性。


编辑:

最后,如果没有new 关键字, 会更好地为您提供的模式提供服务。由于您正在创建并返回一个任意对象,因此您不需要 JS 引擎为您创建一个。因此,如果您只是从此处的代码中完全删除 new,您的代码应该可以工作。

构造函数有一个怪癖。当他们返回一个对象时,他们返回该对象而不是通过new 创建的对象。在这里,您将返回 self,这是您通过 Object.create 自己制作的。如果构造函数返回一个非对象(字符串、数字、函数、null),它实际上会返回this。在咖啡脚本中,由于隐式返回表单函数,这可能会很棘手。而且在使用咖啡脚本类时,构造函数从不返回任何内容,让您可以处理这个奇怪的问题。

【讨论】:

  • Alex,一如既往地很有帮助和启发性。谢谢。我的摘录:使用没有“new”的构造函数,将“public”方法放入原型中,并接受“private”除了函数闭包之外不存在的事实。这样可以构建一个单一的继承链(GGG 指出),但有一些限制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-21
  • 2023-03-07
  • 2016-12-03
相关资源
最近更新 更多