Невозможно прочитать свойство 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 ответов
Есть несколько проблем с вашим кодом:
Вы столкнулись с тем, что является этой проблемой, которая является очень распространенной проблемой для начинающих, посмотрите по этой ссылке. В анонимной функции тела
function (element) { ..
он не получает контекст вашего пользовательского типа, таким образомthis
ссылка на окно вашего браузераВаш
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