【问题标题】:OOP Javascript - Isolate object within classOOP Javascript - 在类中隔离对象
【发布时间】:2011-06-13 01:25:16
【问题描述】:

我正在尝试创建一个可以创建多个实例的主对象,每个实例都继承子对象(具有唯一/隔离的属性)。但是,当我这样做时,对象的属性(在更改后)会针对所有创建的对象而更改。我可能没有正确解释这一点,但这个例子应该很清楚。

Main = function(){};

// Extending the main class with new object. Doing it this way so I can have these in
// separate files.
Main.prototype.foo = {
    bar: 1
}

// First instance of Main().
var A = new Main();

// Second instance of Main().
var B = new Main();

// Set the bar property to different values for each Main() object.
A.foo.bar = 2;
B.foo.bar = 3;

// Both A.foo.bar and B.foo.bar return 3.
alert(A.foo.bar);
alert(B.foo.bar);

我想要实现的是 A.foo.bar 返回 2 和 B.foo.bar 返回 3,这样我就有了彼此独立的孤立对象。

有什么想法吗?我只是错过了一些明显的东西吗?将不胜感激!

【问题讨论】:

  • 为什么要设置两次“foo”?这只是转录错误吗?

标签: javascript prototype-programming


【解决方案1】:

“foo”属性在原型对象上,并且只有其中一个。当您通过任何实例设置它时,您会影响相同的共享属性。

您可以在构造函数中添加实例属性:

  function Main() {
    this.instanceProperty = 1;
  }

那将是每个实例。

原型不是“主模板”或类似的东西;这是一个真实的对象。它不会复制到实例上。相反,运行时知道它在那里,并且当对实例上实际不存在的属性进行引用时,它会知道沿着原型链向上并在那里查找属性。

【讨论】:

    【解决方案2】:

    其他答案或多或少是正确的,但他们缺少的是两者之间存在差异

    Main.prototype.foo = {
        bar: 1
    };
    

    Main.prototype.bar = 1;
    

    在这两种情况下,实例化一个新的Main 将创建一个新实例,在其原型链中具有属性foobar。在这两种情况下,都可以重新定义实例级属性而不影响其他实例:

    function Main() {};
    Main.prototype.foo = {
        bar: 1
    };
    Main.prototype.bar = 1;
    
    a = new Main();
    b = new Main();
    
    a.foo = { bar: 2 };
    console.log(a.foo.bar, b.foo.bar); // 2 1
    
    a.bar = 2;
    console.log(a.bar, b.bar); // 2 1
    

    但是当您实例化一个新的Main 时,实例变量foo 是对单个对象{bar:1}引用,该对象在所有实例之间共享。因此,当您设置a.foo.bar 时,您更改的是公共对象,而不是实例变量;实例变量是引用a.foo

    您不必在构造函数中初始化实例属性。标准方法是直接在原型上设置bar,即Main.prototype.bar = 1,这将为您提供初始化为1 的独立实例变量。但是,如果您需要基于每个实例的更复杂的数据结构(对象、数组或另一个类的实例),那么您不能将其创建为原型上的属性,因为您将给每个实例一个公共对象的引用 - 所以在构造函数内部是要走的路:

    function Main() {
        // instance-level object
        this.foo = {
            bar: 1
        };
    }
    

    【讨论】:

    • 查看这篇出色的帖子以清楚地了解原型的工作原理:javascriptweblog.wordpress.com/2010/06/07/…
    • 我认为“实例变量 foo 是对单个对象的引用”这句话对于理解在 foo 中操作属性的行为很重要。
    【解决方案3】:

    由于您在原型上编辑某些东西,它会影响每个对象。

    但是,您可以这样做:

    A.x = 2;
    B.x = 3;
    

    那么你会有不同的结果。

    或者,你可以有这样的东西:

    Main = function(val){
      this.x = val;
    }
    
    A = new Main(2);
    B = new Main(3);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-05
      • 2013-07-20
      • 1970-01-01
      • 1970-01-01
      • 2017-05-11
      • 2012-07-15
      • 1970-01-01
      相关资源
      最近更新 更多