0

我开始喜欢下面的模式(抱歉,这里是 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 放入原型中,以便引用而不是复制这些函数怎么办?

那时有人可以启发我吗?

4

1 回答 1

1

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

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

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

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

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

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

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

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


编辑:

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

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

于 2012-05-07T22:34:19.893 回答