Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property of undefined of function inside loop

I have the "error: Cannot read property 'shorten' of undefined" error when running my test. I want my loop to run the shorten function to check if the string is longer then 20 characters, and if so limit it to that.

  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 is from another constructor but i mocked it with;

var mockList = { notelist: [{ text: "hello" }, { text: "goodbye" }] };
like image 748
pyan Avatar asked Nov 26 '22 01:11

pyan


1 Answers

There are serveral problems with your code:

enter image description here

  1. You encountered the what is this problem which is a very common problem with beginners, have a look at this link. In the anonymous function body of function (element) { .. it doesn't obtain the context of your custom type, thus this is a reference to your browser window.

  2. Your shorten method is called with a different usage in its semantics. You did not take what it returns, but element is not modified at all with the method.

So, let's try to correct the code for what you attempt to do:

<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 is modified intentionally for the test, in the result it will be shorten as goodbye0123456789012.

like image 72
Ken Kin Avatar answered Dec 15 '22 14:12

Ken Kin