无法读取循环内函数未定义的属性

问题描述 投票:4回答:5

我在运行测试时遇到“错误:无法读取属性'缩短'未定义'错误。我希望我的循环运行缩短函数来检查字符串是否超过20个字符,如果是这样,则将其限制为该字符串。

  function ListView(list) {
    this.list = list;
    this.converted;
  }

  ListView.prototype.convert = function() {
    var output = [];
    this.list.notelist.forEach(function(element) {
      this.shorten(element);
      output += "<li><div>" + element.text + "</div></li>";
    });
    this.converted = "<ul>" + output + "</ul>";
  };

  ListView.prototype.shorten = function(string) {
    if (string.length > 20) {
      return string.substring(0, 20);
    }
    return string;
  };

list来自另一个构造函数,但我用它来嘲笑它;

var mockList = { notelist: [{ text: "hello" }, { text: "goodbye" }] };
javascript string foreach dom-manipulation
5个回答
2
投票

您的代码有几个问题:

  1. 你遇到了这个问题,这对初学者来说是一个非常普遍的问题,看看this link。在function (element) { ..的匿名函数体中,它不会获取自定义类型的上下文,因此this是对浏览器窗口的引用。
  2. 您的shorten方法在其语义中使用不同的用法。你没有拿回它的东西,但是element根本没有用这个方法修改过。

所以,让我们尝试纠正您尝试执行的操作的代码:

<script>
    function ListView(list) {
        this.list = list;
        this.converted;
    }

    ListView.prototype.convert = function () {
        var output = [];

        var that = this;
        this.list.notelist.forEach(function (element) {
            that.shorten(element);
            output += "<li><div>" + element.text + "</div></li>";
        });
        this.converted = "<ul>" + output + "</ul>";
    };

    ListView.prototype.shorten = function (el) {
        var string = el.text;

        if (string.length > 20) {
            el.text = string.substring(0, 20);
        }
    };

    var mockList = { notelist: [{ text: "hello" }, { text: "goodbye0123456789012345" }] };
    var listview1 = new ListView(mockList);
    listview1.convert();
    alert(listview1.converted);

</script>

goodbye0123456789012345被故意修改为测试,结果它将缩短为goodbye0123456789012


1
投票

你在this丢失了forEach绑定尝试:

  ListView.prototype.convert = function() {
    var output = [];
    this.list.notelist.forEach(function(element) {
      this.shorten(element);
      output += "<li><div>" + element.text + "</div></li>";
    }.bind(this));
    this.converted = "<ul>" + output + "</ul>";
  };

要么

this.list.notelist.forEach((element) => {
  this.shorten(element);
  output += "<li><div>" + element.text + "</div></li>";
});

类似于:Passing scope to forEach


0
投票

尝试绑定this

this.list.notelist.forEach(function(element) {
      this.shorten(element);
      output += "<li><div>" + element.text + "</div></li>";
    }.bind(this));

-2
投票

在这种情况下,您可以使用ES6 arrow function来确保在您的函数中维护this

this.list.notelist.forEach((element) => {
  this.shorten(element);
  output += "<li><div>" + element.text + "</div></li>";
});

请记住浏览器上的箭头函数的check the availability。如果您想要更广泛支持的解决方案,请像其他人一样使用bind函数。


-2
投票

forEach接受第二个参数,即thisArg,默认情况下是undefined

试试这个:

   this.list.notelist.forEach(function(element) {
      this.shorten(element);
      output += "<li><div>" + element.text + "</div></li>";
    }, this); // <-- note the `this` argument passed here
© www.soinside.com 2019 - 2024. All rights reserved.