【问题标题】:Existing function as a callback for Array.forEach现有函数作为 Array.forEach 的回调
【发布时间】:2016-01-07 22:44:25
【问题描述】:

这段代码的奇怪行为:

我有一些 Angular 控制器:

.controller('View1Ctrl', ['$scope', 'CrawlServerExecutor', function ($scope, CrawlServerExecutor) {

    $scope.results = [];

    var showResults = function (results) {
        results.forEach(function (result) {
            $scope.results.push(result);
        });
    };

这样写的时候:

    var showResults = function (results) {
        results.forEach($scope.results.push);
    };

我收到此错误: Error: undefined is not an object 试图访问 push 函数,我在调试器中查看了 $scope.results 并且该对象被识别为一个数组,但由于某种原因,在此语法中它没有引用它的 push 函数。我更喜欢这段代码,因为它更优雅。

有人知道为什么会这样吗?

谢谢

【问题讨论】:

  • 您是否尝试过将数组绑定到函数(所以当它被调用时,this 将被正确设置),如results.forEach($scope.results.push.bind($scope.results));
  • @AlexCorreiaSantos - 你当然是对的。为什么不发布答案?
  • 我没有机会测试,只是想从头顶上弄清楚,所以我不想给出错误的答案。很高兴它起作用(我已将其添加为答案)
  • showResults 是否被重复调用?结果是汇总还是替换?并且参数 (results) 是类数组对象的数组吗?
  • 那为什么不简单地将值分配给属性,例如:$scope.results = results;

标签: javascript angularjs callback


【解决方案1】:

您需要将数组绑定到函数,这样才能在正确的上下文中调用它(this 设置正确)。

results.forEach($scope.results.push.bind($scope.results));

【讨论】:

  • 这会导致这个错误:Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys.
  • 如果您多次使用相同的值调用该函数,那么您可以在插入之前清除列表作为快速修复$scope.results = [],然后继续执行forEach
  • @johni:这是另一个故事,答案是正确的,您可以接受答案并在 SO 中提出新问题。顺便说一句,我建议downvoter 评论它的downvote。
【解决方案2】:

在后一种表示法中,您传递了 push 函数的引用。因此,在 push 函数本身(这是一些定义的 javascript 代码)内部,“this”-reference 将是“window”。 如果您在没有任何绑定上下文的情况下调用函数,就会发生这种情况。 在第一种情况下,您调用 $scope.results.push(result),因此上下文(以及 push 函数内的“this”引用)将是 $scope.results 数组。 在 javaScript 中,“this”可以根据上下文而改变。

现在的问题是 Array-Prototype 的 push 函数假定上下文是数组本身,而这里不是这样。

所以你可以做的是使用“绑定”方法将特定上下文“绑定”到裸函数。

所以你可以试试

results.forEach ($scope.results.push.bind($scope.results));

现在 push 函数中的上下文(这个变量)将再次成为数组 $scope.results 并且该函数将正常工作

【讨论】:

    【解决方案3】:

    您会遇到异常,因为当调用push(即函数Array.prototype.push)时,它在没有上下文的情况下被调用,没有任何this 值可操作。 这样做就像在 undefined 值上调用它,这是错误消息告诉你的......

    您的基本操作是连接 2 个数组并保留最终结果。

    您无需自己迭代数组即可。

    您可以通过以下方式简化代码:

    $scope.results = $scope.results.contact(results);
    

    或者,如果您更喜欢 $scope.results 的“就地突变”,请尝试:

    [].push.apply($scope.results, results);
    

    或者,如果您真的想自己迭代并使用forEach,请使用最后一个参数传递this 上下文:

    results.forEach($scope.results.push, $scope.results);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 2018-07-11
      相关资源
      最近更新 更多