【问题标题】:Is there a way to change/redirect "indirect" self-references?有没有办法改变/重定向“间接”自引用?
【发布时间】:2016-08-12 17:07:05
【问题描述】:

我正在使用 Knockout.js 开发一个网站,但我的问题更笼统,所以不要专注于此。

我通过变量名引用对象本身,在本例中为viewModel,如下所示:

var viewModel = {
    propA: "propA",
    fnA: function () {
        alert("I am " + viewModel.propA); //the same as this.propA
    }
};

这样,当涉及到子对象和其他“花哨”的东西时,我不会遇到任何麻烦。

现在,我需要将另一个对象合并到我的 viewModel 中,但遇到了引用问题:

g_test = {}; //The way with this global variable is just for demonstration purposes

(function () {
    var viewModel = {
        propA: "propA",
        fnA: function () {
            alert("I am " + viewModel.propB);
        }
    };
    g_test.vmA = viewModel;
})();

(function () {
    var viewModel = {
        propB: "propB",
        fnB: function () {
            alert("I am " + viewModel.propA);
        }
    }

    /** merge viewModel "A" into viewModel "B" */
    var vmA = g_test.vmA;
    for (var key in vmA) {
        if (vmA.hasOwnProperty(key)) {
            viewModel[key] = vmA[key];
        }
    }

    viewModel.fnA(); //I am undefined
    viewModel.fnB(); //I am propA
})();

如您所见,fnB 知道propA,但fnA 不知道propB

使用this 作为对viewModel 对象的引用但是可以完成这项工作。但我不想遍历我的整个对象并将每个viewModel 替换为this 或在需要时引入相应的“辅助变量”,因为这会花费我很多时间。另外,在我看来,这意味着不可能合并两个彼此没有双向知识的对象。

有没有一种有意义的方式让fnA 中的viewModel 变量指向viewModel "B" 而不必知道viewModel "B"?

【问题讨论】:

  • JavaScript 具有词法范围。在fnA 中更改viewModel 的唯一方法是为其分配一个新值。但这在您的示例中是不可能的,因为viewModel 是 IIFE 的本地对象。
  • this.propB 替换viewModel.propB 就可以了
  • 使用this 就是答案。这就是它的用途。
  • 另请注意,使用您的方法,fnB 函数会打印复制的 propA,而不是原始值(因此它们可能具有不同的值)。
  • @MichaelBest 我知道,我想要那个副本。但 JAG 和您的建议真的是“微创”解决方案吗?这当然不是不可能的,但是如果可能的话,我真的很想避免大量的努力。不仅是出于努力的原因,而且还因为有可能以模块化方式向该对象/视图模型添加部件。

标签: javascript object knockout.js merge self-reference


【解决方案1】:

创建多个视图模型然后尝试合并它们似乎是一种有问题的方法,我不知道您想用它来实现什么。可能有更好的方法(至少,使用this 将是创建mixins 的正确选择)。但是假设要么有充分的理由,要么现在返工太费力了,让我们看看你的问题。

您有两个 viewModel,并且您希望以这样一种方式合并它们,使每个视图模型都知道另一个视图模型的成员。你在一个方向合并它们,所以 B 知道 A,但 A 不知道 B。你也需要合并另一个方向。 Object.assign 是一种方便的方式来执行您的循环所做的事情,但如果您使用的是之前的Object.assign 浏览器,您可以添加另一个通过viewModel 的循环并将其中的属性复制到vmA

结果是您有两个视图模型,它们的方法相互引用。每个都有propApropBfnAfnB,但fnA(在两个对象中)指的是对象A的成员,反之亦然。

g_test = {}; //The way with this global variable is just for demonstration purposes

function mergeObjects(obj1, obj2) {
  Object.assign(obj1, obj2);
  Object.assign(obj2, obj1);
}

(function() {
  var viewModel = {
    propA: "propA",
    fnA: function() {
      alert("fnA: I am " + viewModel.propB);
    }
  };
  g_test.vmA = viewModel;
})();

(function() {
  var viewModel = {
    propB: "propB",
    fnB: function() {
      alert("fnB: I am " + viewModel.propA);
    }
  }

  mergeObjects(g_test.vmA, viewModel);

  // to demonstrate which value is outputted by which function
  g_test.vmA.propA = "A.propA";   // not used
  g_test.vmA.propB = "A.propB";   // used by fnA
  viewModel.propA = "B.propA";    // used by fnB
  viewModel.propB = "B.propB";    // not used

  viewModel.fnA(); //I am A.propB
  viewModel.fnB(); //I am B.propA
  // also
  g_test.vmA.fnA();
  g_test.vmA.fnB();
})();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-19
    • 2019-05-19
    • 1970-01-01
    • 2015-02-16
    • 1970-01-01
    • 2019-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多