Невозможно прочитать свойство undefined функции внутри цикла

У меня ошибка "ошибка: невозможно прочитать свойство" сократить "из неопределенного" при запуске моего теста. Я хочу, чтобы мой цикл запускал укороченную функцию, чтобы проверить, длиннее ли строка, чем 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;
  };

список из другого конструктора, но я поиздевался с ним;

var mockList = { notelist: [{ text: "hello" }, { text: "goodbye" }] };

5 ответов

Есть несколько проблем с вашим кодом:

  1. Вы столкнулись с тем, что является этой проблемой, которая является очень распространенной проблемой для начинающих, посмотрите по этой ссылке. В анонимной функции тела 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,

Вы потеряли 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>";
});

Аналогично: передача области действия forEach

Попробуй связыванием this

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

В этом случае можно использовать функцию стрелки ES6, чтобы this поддерживается в вашей функции.

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

Не забудьте проверить наличие функций стрелок в браузерах. Если вы хотите более широко поддерживаемое решение, используйте bind функционировать, как другие уже упоминали.

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
Другие вопросы по тегам