获取TypeError: Cannot set property '0'尝试向数组添加时未定义的

Getting TypeError: Cannot set property '0' of undefined when trying to add to array

本文关键字:数组 添加 未定义 property set TypeError 获取 Cannot      更新时间:2023-09-26

我正在努力学习打字。在这次尝试中,我试图从我创建的web服务中获得一个数字数组。

我有下面的Typescript类:

class GameMap2 {
    Grid: Uint8Array;
    width: number;
    height: number;
    constructor(height: number, width: number) {
        this.height = height;
        this.width = width;
        this.Grid = new Uint8Array(height * width);
    }
    generateMap() {
        alert("calling generate");
        $.ajax({
            url: "/api/Maps/" + this.width + "/" + this.height,
            async: false,
            dataType: 'json',
            success: function(data) {
                alert("Ajax success");
                for (var idx = 0; idx < data.length; idx++) {
                    this.Grid[idx] = data[idx];
                }
            }
        });
    }
}

从webservice,我将得到类似:[1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,1,1,0,0,0,1,0,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,1,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1]现在,当我尝试遍历这个结果并将其放入Grid数组时,我得到了错误:TypeError: Cannot set property '0' of undefined

如果我把它改为This.Grid.Push(data[idx]);,我得到未定义的错误。在我看来,我的网格数组实际上不在我的ajax回调的范围内。这是真的吗,还是我做错了什么?还有别的方法可以让我的数组进入javascript数组吗?

事实上,这个问题是由TypeScript直接解决的。这个特性叫做arrow function,它会像下面这样改变你的代码定义

class GameMap2 { 
    ...
    constructor(height: number, width: number) { ... }
    generateMap() {
        alert("calling generate");
        $.ajax({
            // instead of this
            // success: function(data) {
            // use this style, and the compiler will do the magic
            // of keeping correct "this" for us
            success: (data) => {
                alert("Ajax success");
                for (var idx = 0; idx < data.length; idx++) {
                    this.Grid[idx] = data[idx];
                }
            }
         ....

参见TypeScript箭头函数教程(small cite)

…箭头函数表达式是函数表达式的一种紧凑形式,它省略了function关键字,并具有this的词法作用域。基本上,箭头函数可以帮助您自动保留一定的范围。如果你看一下编译器输出的代码,它只是创建了一个var _this = this;并且在函数内部使用。

这是因为this在成功回调中改变了上下文。引用this并使用它:

generateMap() {
  alert("calling generate");
  var _this = this;
  $.ajax({
    url: "/api/Maps/" + this.width + "/" + this.height,
    async: false,
    dataType: 'json',
    success: function(data) {
      alert("Ajax success");
      for (var idx = 0; idx < data.length; idx++) {
        _this.Grid[idx] = data[idx];
      }
    }
  });
}