【问题标题】:Javascript nested function attribute inheritanceJavascript嵌套函数属性继承
【发布时间】:2015-04-04 16:16:26
【问题描述】:

我试图在嵌套函数中使用函数的属性,但我不知道如何,没有传递父函数。

示例:

function foo() {
    this.baz = 'baz'
    this.bar = new bar()
}

function bar() {
    this.bla = 'bla'
}

bar.prototype.func = function() {
    console.log(...) // this should return 'baz' (attr baz of foo())
}

到目前为止,我尝试过这个:

function foo() {
    this.baz = 'baz'
    this.bar = new bar(this)
}

function bar(foo) {
    this.bla = 'bla'
    this.foo = foo
}
bar.prototype.func = function() {
    console.log(this.foo.baz)
}

有没有一个好的模式来完成这个?因为我的解决方法是一团糟

编辑:

因为你们中的一些人想要一个更真实的例子:

function Game() {
    this.world = {
        x: 200,
        y: 300
    }
    this.players = {
        one: new Player()
        two: new Player()
    }
}

function Player() {
    this.size = {x:1,y:2}
    this.position = {
        x: world.x - this.size.x, // i need to access games world attribute
        y: 0
    }
}

但这不是我在 Player 类中需要的 Game 类的唯一属性..

【问题讨论】:

  • 这似乎是关于 JavaScript 作用域如何工作的一半问题和关于继承如何工作的一半问题。也许如果您提供更多现实生活中的示例,我们可以就good 方法提出更好的建议来做您想做的事情。就目前而言,我的回应是“只需将foo 引用传递给bar
  • 在您的示例中,bar 不继承自 foobar 上没有可以访问 foo 属性的原型属性。您在第一个示例中所做的可能相当于依赖注入,但没有任何继承。关于第二个例子,也没有继承,但是你使用bar作为foo的装饰器,所以你可以做this.foo.baz。这对于装饰器的这种实现是完全有效的。
  • 我支持@brianvaughn - 目前看起来不错,但可能并不取决于实际需要,而且确实有更好的方法。
  • 我同意@brianvaughn 关于需要一个真实生活例子的观点。当前的问题没有解释您要做什么。如果您想在bar 中使用baz,您可以在第二个sn-p 中使用它,或者您可以将foo 实例化,您在bar 中执行的所有操作都可以使用this.method,而是使用@987654338 @来自foo。上帝,我讨厌这些无处不在的虚拟变量名。
  • 感谢您的 cmets.. 我添加了一个真实的例子

标签: javascript function class inheritance


【解决方案1】:

更新答案

您可能想了解encapsulation。鉴于您更新的示例,您可以将 Game 的引用传递给您的每个 Player 实例,如下所示:

function Game() {
    this.world = {
        x: 200,
        y: 300
    }
    this.players = {
        one: new Player(this),
        two: new Player(this)
    }
}

function Player(game) {
    this.game = game;
    this.size = {x:1,y:2}
    this.position = {
        x: game.world.x - this.size.x, // i need to access games world attribute
        y: 0
    }
}
Player.prototype.anotherFunction = function() {
  console.log(this.game); // Also has access to `this.game`
}

正如 Vld@ 所说,可能有更好的方法来完成您在此示例中尝试执行的操作,但我怀疑这是一个更普遍的问题。

原答案

实现您想要做的事情的一种方法是使用继承,如下所示:

function Foo() {
  this.baz = 'baz';
}
function Bar() {
  this.bla = 'bla';
  Foo.call(this);
}
Bar.prototype = Object.create(Foo.prototype);

console.log(new Bar().baz); // "baz"

【讨论】:

  • 感谢您的回答。在玩家原型中使用game 怎么样?我也可以在那里使用它吗?
  • 我不确定我是否理解您的问题。但是...我会更新我的答案以反映我认为你在问什么
  • 是的,这正是我所要求的。但是现在您必须将游戏实例存储在一个属性中,这是我已经拥有的。所以如果这是我回答问题的最佳方式。感谢您的帮助!
  • 正如我们中的一些人最初暗示的那样,“最佳方法”取决于问题的具体情况。它也可以是主观的。 :) 这似乎是处理您所描述的问题的合理方法。祝你好运!
  • 我有点不同意将整个Game 对象传递给Players。他们只对画布的大小感兴趣,所以他们当然可以接受Player = function(width) {this.position {x : width - this.size.x}} 或接受整个画布。事实上,我更倾向于让玩家接受一个名为datawidth(或x,如果你愿意)的普通对象是它的一个属性。这意味着如果 Player 将来需要其他东西,它们将作为配置传入。
【解决方案2】:

如果您不想将整个“游戏”函数传递给“玩家”,并且您希望维护某些变量的隐私并允许某些玩家方法访问它,我推荐以下:

function Game() {

    // Declare private variables as 'var' here

    this.world = {
        x: 200,
        y: 300
    }
    this.players = {
        one: new Player()
        two: new Player()
    }

    // The following players methods will have access to 
    // both public and private interface of Game 
    this.players.one.position = {
        x: this.world.x - this.players.one.size.x, 
        y: 0
    }
    this.players.two.position = this.players.one.position;
}

function Player() {
   // Declare private variables for player as 'var' here 

   this.size = {x:1,y:2}
}

【讨论】:

  • 我在玩家原型中需要的属性呢?
  • 如果您的播放器原型需要任何属性,那么您应该将其作为参数传递给构造函数,例如 one: new Player(specs)(假设您的原型方法是使用 this 构建的)跨度>
猜你喜欢
  • 2020-01-19
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 2012-08-15
相关资源
最近更新 更多