代码之家  ›  专栏  ›  技术社区  ›  Guillaume D

在回调中初始化变量时遇到未定义属性的困难

  •  0
  • Guillaume D  · 技术社区  · 6 年前

    我在Nodejs中有一个API REST服务器,它有一个Express框架,可以与我用Angular7制作的前端进行通信。服务器存储并发送一些分数对象,模型的正面和背面是相同的。

    问题是,我面临以下错误:

    错误类型错误:无法设置未定义的“UserScore”属性
    错误类型错误:无法读取未定义的属性“highscore”
    错误类型错误:无法设置未定义的属性“highscore”

    出现错误的组件:

    import {AfterViewInit, Component, ElementRef, HostListener, OnInit, 
    ViewChild} from '@angular/core';
    import {ScoreService} from './services/score.service';
    import {Score} from './models/score';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent implements OnInit, AfterViewInit {
      contentScores: {
        highScore: number,
        userScore: Score
      };
      scroll: boolean;
      badgeHidden: boolean;
      private yOffSet: any;
    
      @ViewChild('navbar') navElement: ElementRef;
    
      constructor(private score: ScoreService) {
        this.scroll         = false;
        this.badgeHidden    = true;
      }
    
      ngOnInit(): void {
        this.score.getHighScore().subscribe( score => {
          console.log('Score value: ' + score.score);
          console.log('Object: ' + score);
          this.contentScores.highScore = score.score;
        });
        this.score.getScoreOnIp().subscribe( score => {
          console.log('Score value: ' + score.score);
          console.log('Object: ' + score);
          this.contentScores.userScore = score;
        });
      }
    
      ngAfterViewInit(): void {
        this.yOffSet = this.navElement.nativeElement.offsetTop;
      }
    
      onClickReset(): void {
        console.log('----------INFO------------');
        console.log(this.contentScores.highScore);
        console.log(this.contentScores.userScore.score);
        console.log(this.contentScores.userScore._id);
        console.log('--------------------------');
        this.score.deleteScore(this.contentScores.userScore._id);
      }
    
      @HostListener('window:scroll', ['$event'])
      onWindowScroll(): void {
        const currYOffset = window.pageYOffset;
    
        if (this.yOffSet < currYOffset) {
          this.scroll = true;
        } else {
          this.scroll = false;
        }
      }
    }
    

    以及调用变量时视图中的位置:

    <p class="dropdown-item-text">Le meilleur score enregistré est actuellement: <span class="warn-content">{{ contentScores.highScore }}</span></p>
                <p class="dropdown-item-text">Votre meilleur score est: <span class="warn-content">{{ contentScores.userScore.score }}</span></p>

    我不明白为什么我不能用API调用中的值实例化一个未定义的对象。请注意,console.log显示的是值,所以从恢复的数据中不存在问题。问题是关于存储值的对象的声明。

    我对安古拉7的发展很陌生,所以很抱歉,如果答案可能很明显,我提前为我的英语道歉,我知道这不是很好。

    1 回复  |  直到 6 年前
        1
  •  1
  •   rpadovani    6 年前

    contentScores 尚未初始化。

    如果用空对象初始化它,那么它将工作

    contentScores: {
        highScore: number,
        userScore: Score
      } = {};
    

    这是由于代码是如何被转换成JavaScript的。看看这个类型脚本代码:

    class Greeter {
        contentScores: {
            highScore: string,
        };
        constructor(message: string) {
            this.contentScores.highScore = message;
        }
    }
    
    let greeter = new Greeter("world");
    

    它将成为这个javascript代码:

    var Greeter = /** @class */ (function () {
        function Greeter(message) {
            this.contentScores.highScore = message;
        }
        return Greeter;
    }());
    var greeter = new Greeter("world");
    

    正如你所看到的, this.contentScores 未在任何位置初始化。

    另一方面,如果您将其创建为空对象,那么它将被正确初始化:

    class Greeter {
        contentScores: {
            highScore: string,
        } = {};
        constructor(message: string) {
            this.contentScores.highScore = message;
        }
    }
    
    let greeter = new Greeter("world");
    

    变成

    var Greeter = /** @class */ (function () {
        function Greeter(message) {
            this.contentScores = {};
            this.contentScores.highScore = message;
        }
        return Greeter;
    }());
    var greeter = new Greeter("world");