为什么嵌套对象在遍历时返回未定义?

时间:2019-04-15 17:12:15

标签: javascript for-loop

https://plnkr.co/edit/aZi06HM9CkM9lScy9LS3?p=preview

$scope.lettersandthings = [
   { letter: "a", things: [{name:"airplane"}, {name:"apple"}, {name:"alligator"}]}, 
   { letter: "b", things: [{name:"bath"}, {name:"bicycle"}, {name:"bear"}]},
   { letter: "c", things: [{name:"chair"}, {name:"carrot"}, {name:"cat"}]}
 ]; 

$scope.allchildrenLength = 9;
$scope.allparentsLength = 3;

ng-click="myFunction(0)" <!-- indexParent -->
ng-click="myFunction(1)"
ng-click="myFunction(2)"

for(i=0; i < $scope.allchildrenLength; i++) {
    for(var j=0; j < $scope.allparentsLength; j++)  {
      $scope.lettersandthings[j].things[i].open = !$scope.lettersandthings[indexParent].open || $scope.lettersandthings[j].open ? false : $scope.lettersandthings[j].things[i].open;
    }
  }

myFunction()的这一部分给了我错误(但是仍然可以正常工作):

  • TypeError:无法读取未定义的属性“ open”
  • TypeError:无法设置未定义的属性“ open”

我读到您需要使用“ for ... in”循环来访问嵌套对象,但是我不确定具体如何针对我的情况进行操作。我在这里尝试过,但仍然遇到相同的错误(并且停止运行):

for(var lttr in $scope.lettersandthings) {
    for(var thng in $scope.lettersandthings[lttr]) {
      $scope.lettersandthings[lttr].things[thng].open = !$scope.lettersandthings[indexParent].open || $scope.lettersandthings[lttr].open ? false : $scope.lettersandthings[lttr].things[thng].open;
    }
  }

即使它正在工作,但我希望它没有错误。谢谢。

完整代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>title</title>

    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    
    <style type="text/css">
      .section {
        margin: 20px;
        padding: 10px;
      }

     
    </style>

  </head>
  <body>
  
    <div ng-app="myApp" ng-controller="myCtrl">

      <script type="text/ng-template" id="group-template.html">
        <div class="panel-heading">
          <h4 class="panel-title" style="color:#fa39c3">
            <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading">
              <span uib-accordion-header ng-class="{'text-muted': isDisabled}">
                {{heading}}
              </span>
            </a>
          </h4>
        </div>
        <div class="panel-collapse collapse" uib-collapse="!isOpen">
          <div class="panel-body" style="text-align: right" ng-transclude></div>
        </div>
      </script>

      <div class="section">
        <button ng-click="myFunction(0)">Toggle a</button>
          <button ng-click="lettersandthings[0].things[0].open = !lettersandthings[0].things[0].open">Toggle airplane</button>
          <button ng-click="lettersandthings[0].things[1].open = !lettersandthings[0].things[1].open">Toggle apple</button>
          <button ng-click="lettersandthings[0].things[2].open = !lettersandthings[0].things[2].open">Toggle alligator</button>
      </div>

      <div class="section">
        <button ng-click="myFunction(1)">Toggle b</button>
          <button ng-click="lettersandthings[1].things[0].open = !lettersandthings[1].things[0].open">Toggle bath</button>
          <button ng-click="lettersandthings[1].things[1].open = !lettersandthings[1].things[1].open">Toggle bicycle</button>
          <button ng-click="lettersandthings[1].things[2].open = !lettersandthings[1].things[2].open">Toggle bear</button>
       </div>

      <div class="section">
        <button ng-click="myFunction(2)">Toggle c</button>
          <button ng-click="lettersandthings[2].things[0].open = !lettersandthings[2].things[0].open">Toggle chair</button>
          <button ng-click="lettersandthings[2].things[1].open = !lettersandthings[2].things[1].open">Toggle carrot</button>
          <button ng-click="lettersandthings[2].things[2].open = !lettersandthings[2].things[2].open">Toggle cat</button>
      </div>


    <div id="accordion-wrapper">

      <uib-accordion close-others="oneAtATime">
          <div uib-accordion-group  id="accordion" ng-repeat="l in lettersandthings" heading="{{l.letter}}" class="eachLetter" id="{{l.id}}" is-open="l.open">

            <!-- nested accordion -->
            <uib-accordion close-others="oneAtATime">
              <div uib-accordion-group id="inner-accordion" class="innercontent" ng-repeat="thing in l.things" heading="{{thing.name}}" is-open="thing.open">
                <p>{{thing.name}} content</p>
              </div>  
            </uib-accordion>

          </div>
      </uib-accordion>  

    </div>


<script type="text/javascript">

  var myApp = angular.module('myApp', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);

  myApp.controller('myCtrl', function($scope) {

    $scope.oneAtATime = true;

    $scope.allchildrenLength = 9;
    $scope.allparentsLength = 3;

    $scope.myFunction = function(indexParent) {

    // First close the outer tab
    $scope.lettersandthings[indexParent].open = !$scope.lettersandthings[indexParent].open;

      // Close all inner tabs if the outer parent is closed or any other tab is opened
      for(i=0; i < $scope.allchildrenLength; i++) {
        for(var j=0; j < $scope.allparentsLength; j++)  {
          $scope.lettersandthings[j].things[i].open = !$scope.lettersandthings[indexParent].open || $scope.lettersandthings[j].open ? false : $scope.lettersandthings[j].things[i].open;
        }
      }
      
    }
  

    $scope.lettersandthings = [
       { letter: "a", things: [{name:"airplane"}, {name:"apple"}, {name:"alligator"}]}, 
       { letter: "b", things: [{name:"bath"}, {name:"bicycle"}, {name:"bear"}]},
       { letter: "c", things: [{name:"chair"}, {name:"carrot"}, {name:"cat"}]}
     ];    

  });

</script>



  </body>
</html>

1 个答案:

答案 0 :(得分:1)

例如,您正在访问things[3],但是尽管总共有9件事,但是每个things数组只有3个元素长,因此第四个元素(之后都是第9个元素)是undefined

在迭代之前,您应该切换内循环和外循环并检查每个things数组的长度

for(j=0; j < $scope.allparentsLength; j++) { 
  for(i=0; i< $scope.lettersandthings[j]. things.length; i++) { 
    $scope.lettersandthings[j].things[i].open = !$scope.lettersandthings[indexParent].open || $scope.lettersandthings[j].open ? false : $scope.lettersandthings[j].things[i].open; 
  } 
}