尝试在 p5.js 中调用多行字符串时出现 TypeError
Getting TypeError when trying to call multiline string in p5.js
我一直在尝试找出一种解决方案,将单行句子(我在我的代码中称为 "statements")并在我的草图上将它们变成多行句子。这个问题与 another question I posted on SO 直接相关,我被要求 post 这个新问题作为一个新问题。
@KevinWorkman 的解决方案让我明白了这一点。但是,当我尝试 运行 程序时,我得到了一个 TypeError: Cannot read property 'display' of undefined
。加载了草图,但是当我在草图中单击以启动动画时,出现了该错误。我认为这是因为我原来的 statements[]
数组现在不再是可以在我的 draw()
函数中调用的类型。但是我的知识不够了解问题是什么,我已经查看了我所有的 JS 和 p5.js 参考资料,但找不到解决方案。
我正在 post 编写我的完整代码,以努力提供一个最小的、完整的、可验证的示例。尽管事实上,作为一名作家,我发现 "minimal" 和 "complete" 是相互矛盾的术语,因此非常令人困惑,这里是:
var clContext;
var speed = 0.8;
var statements = [];
var canvas;
//load the table of Clinton's statements and their polarity
function preload() {
clContext = loadTable("cl_context_rev.csv", "header");
}
function setup() {
canvas = createCanvas(680, 420);
canvas.mousePressed(inWidth);
background(51);
noStroke();
// iterate over the table rows called in 'preload()' from .csv file
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
}
function draw() {
if (mouseIsPressed) {
background(51);
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
}
}
// Function to align statements, categories, and polarity
function Statement(polarity, statement) {
// Break up single-line statements in order to display as multiline
this.statement = split(statement, "<br>");
this.polarity = polarity;
this.x = random(width);
this.y = random(height);
this.dx = random(-speed, speed);
this.dy = random(-speed, speed);
}
// Attach pseudo-class methods to prototype;
// Maps polarity to color and x,y to random placement on canvas
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
// Make statements reappear if they move off of the sketch display
if(this.x > width+10){
this.x = -10
}
if(this.y > height+10) {
this.y = -10
}
// Map positive/negative statements to colors
if(this.polarity == -1){
fill(229,121,59);
}
else if(this.polarity == 1){
fill(97,93,178);
}
textSize(14);
// Was directed to add both 'text' statements
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
}
// Create functions for hiding and showing statements
function inWidth() {
width = width+5;
};
注:
console.log(typeof this.statement[0]) // returns 'undefined'
console.log(typeof this.statement[1]) // returns 'undefined'
console.log(split(statement, "<br>")) // returns 'undefined'
console.log(statements) // returns 'object'
console.log(statements.length) // returns 20
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
我认为这里的最后一行应该在 for 循环内,以便执行您想要的操作。
您的错误意味着您正试图对未定义的值调用 display() 方法。当循环遍历 statements 数组时,调用 display() 方法的唯一位置是在 draw() 函数内部。这意味着您的 statements 数组在某一时刻包含一个未定义的值。您可以通过控制台记录数组来验证这一点。
我怀疑你有未定义值的原因是因为当你试图在 setup() 函数中填充语句数组时,你只调用 statements[i] =
一次,在你的 for 循环完成后。此时 i
的值是 for 循环结束时的值,因此您的 statements 数组成为一个数组,其中第 i 个元素是您设置的任何值,所有先前的元素都是未定义。
正确代码:
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
statements[i] = new Statement(polarity, statement);
// OR statements.push(new Statement(polarity, statement));
}
作为通用的 JavaScript 编码风格原则,使用 Array.push() 而不是直接赋值来将项目添加到数组也是一个好主意。
马顿的回答是正确的。我给它一个 upvote,我认为你应该接受它。但我会尝试对其进行扩展,因为我不确定您是否理解它在说什么。
让我们看看这些行:
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
请 运行 通过此代码和一些示例数据。假设您有 3 行。
- 你第一次运行通过循环,
i
是0
。你得到一个 statement
和一个 polarity
,但你不对它们做任何事情。
- 你第二次运行通过循环,
i
是1
。你得到一个 statement
和一个 polarity
,但你不对它们做任何事情。
- 你第三次运行通过循环,
i
是2
。你得到一个 statement
和一个 polarity
,但你不对它们做任何事情。
- 然后循环退出。
statement
和 polarity
变量超出范围,因此它们是 undefined
。与 i
变量相同。
基本上,该循环不执行任何操作。然后我们到达这一行:
statements[i] = new Statement(polarity, statement);
但我们知道 i
、polarity
和 statement
是未定义的,所以您真正要做的是:
statements[undefined] = new Statement(undefined, undefined);
你说这个有用,但我很怀疑。你在这里做什么没有任何意义。该语句绝对属于 for 循环,这是我对 .
的回答中的位置
但是按照您现在的方式,数组中没有添加任何内容,除了未定义索引处的内容。那么我们就到了这一行:
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
现在,我敢打赌 statements.length
是 1,因为您在一个未定义的索引处有一些东西(也许那个索引是 i
的最后一个值,我不知道)。但是您肯定在索引 0
处没有任何内容。那么当你进入这个循环时,i
是 0
,但你在那个索引处没有任何东西。换句话说,statements[0]
是未定义的。所以内线真的是这样做的:
undefined.display();
这就是导致您出错的原因。解决第一个问题将消除此错误,因为您实际上是在向数组中添加内容。
此外,请注意以下几行:
// Was directed to add both 'text' statements
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
我给你的这段代码只是一个例子。你必须在这里做一些更智能的事情。我只是向您展示了如何访问 statement
数组的两个索引。您必须实际检查此数组的长度并循环遍历句子才能执行某些操作。那是什么完全取决于你想要发生什么。
关于一般调试
您似乎遇到了很多问题,因为您试图同时处理所有事情。如果您开始以更小的块工作,您会省去很多麻烦。与其尝试将此功能添加到您的大主草图中,不如尝试先让一个较小的示例草图工作?尝试对这些值进行硬编码,这样您就可以准确地看到 split()
函数发生了什么。使用 println()
语句来了解发生了什么。尝试一次添加所有内容只会让您和我们感到困惑。
请注意,这不是对 MCVE 的请求(因为我上次提到它时你很生气),但老实说,你能做的最好的帮助自己的事情就是从更小的步骤开始工作。
您也可以考虑切换到常规处理(Java 模式),因为它可以为您提供有关此类错误的更多信息。
我终于能够通过对代码进行一些简单的更改来解决此问题。一旦我想到它,它似乎非常明显,我完全不确定为什么我花了这么长时间才弄明白。
我首先更改 setup()
代码:
function setup() {
canvas = createCanvas(680, 420);
canvas.mousePressed(inWidth);
background(51);
noStroke();
// iterate over the table rows called in 'preload()' from .csv file
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
var stateSplit = split(statement, "<br>"); // split the statements in setup to avoid issues elsewhere
for (var j = 0; j < stateSplit.length; j++) {
var stateJoin = join(stateSplit, "\n"); // join the statements, inserting a line break, to make a new array
statements[i] = new Statement(polarity, stateJoin); // put this in the for loop (per @marton)
}
}
}
然后我修改了我的构造函数和原型显示函数如下:
摆脱了这个,因为它只分解了语句,但没有加入它们:
this.statement = split(statement, "<br>");
并将其替换为:
this.stateJoin = stateJoin;
然后我摆脱了这些:
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
并改用这个:
text(this.stateJoin, this.x, this.y)
瞧!感谢@marton 和@KevinWorkman 的建议。
我一直在尝试找出一种解决方案,将单行句子(我在我的代码中称为 "statements")并在我的草图上将它们变成多行句子。这个问题与 another question I posted on SO 直接相关,我被要求 post 这个新问题作为一个新问题。
@KevinWorkman 的解决方案让我明白了这一点。但是,当我尝试 运行 程序时,我得到了一个 TypeError: Cannot read property 'display' of undefined
。加载了草图,但是当我在草图中单击以启动动画时,出现了该错误。我认为这是因为我原来的 statements[]
数组现在不再是可以在我的 draw()
函数中调用的类型。但是我的知识不够了解问题是什么,我已经查看了我所有的 JS 和 p5.js 参考资料,但找不到解决方案。
我正在 post 编写我的完整代码,以努力提供一个最小的、完整的、可验证的示例。尽管事实上,作为一名作家,我发现 "minimal" 和 "complete" 是相互矛盾的术语,因此非常令人困惑,这里是:
var clContext;
var speed = 0.8;
var statements = [];
var canvas;
//load the table of Clinton's statements and their polarity
function preload() {
clContext = loadTable("cl_context_rev.csv", "header");
}
function setup() {
canvas = createCanvas(680, 420);
canvas.mousePressed(inWidth);
background(51);
noStroke();
// iterate over the table rows called in 'preload()' from .csv file
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
}
function draw() {
if (mouseIsPressed) {
background(51);
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
}
}
// Function to align statements, categories, and polarity
function Statement(polarity, statement) {
// Break up single-line statements in order to display as multiline
this.statement = split(statement, "<br>");
this.polarity = polarity;
this.x = random(width);
this.y = random(height);
this.dx = random(-speed, speed);
this.dy = random(-speed, speed);
}
// Attach pseudo-class methods to prototype;
// Maps polarity to color and x,y to random placement on canvas
Statement.prototype.display = function() {
this.x += this.dx;
this.y += this.dy;
// Make statements reappear if they move off of the sketch display
if(this.x > width+10){
this.x = -10
}
if(this.y > height+10) {
this.y = -10
}
// Map positive/negative statements to colors
if(this.polarity == -1){
fill(229,121,59);
}
else if(this.polarity == 1){
fill(97,93,178);
}
textSize(14);
// Was directed to add both 'text' statements
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
}
// Create functions for hiding and showing statements
function inWidth() {
width = width+5;
};
注:
console.log(typeof this.statement[0]) // returns 'undefined'
console.log(typeof this.statement[1]) // returns 'undefined'
console.log(split(statement, "<br>")) // returns 'undefined'
console.log(statements) // returns 'object'
console.log(statements.length) // returns 20
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
我认为这里的最后一行应该在 for 循环内,以便执行您想要的操作。
您的错误意味着您正试图对未定义的值调用 display() 方法。当循环遍历 statements 数组时,调用 display() 方法的唯一位置是在 draw() 函数内部。这意味着您的 statements 数组在某一时刻包含一个未定义的值。您可以通过控制台记录数组来验证这一点。
我怀疑你有未定义值的原因是因为当你试图在 setup() 函数中填充语句数组时,你只调用 statements[i] =
一次,在你的 for 循环完成后。此时 i
的值是 for 循环结束时的值,因此您的 statements 数组成为一个数组,其中第 i 个元素是您设置的任何值,所有先前的元素都是未定义。
正确代码:
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
statements[i] = new Statement(polarity, statement);
// OR statements.push(new Statement(polarity, statement));
}
作为通用的 JavaScript 编码风格原则,使用 Array.push() 而不是直接赋值来将项目添加到数组也是一个好主意。
马顿的回答是正确的。我给它一个 upvote,我认为你应该接受它。但我会尝试对其进行扩展,因为我不确定您是否理解它在说什么。
让我们看看这些行:
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
}
statements[i] = new Statement(polarity, statement);
请 运行 通过此代码和一些示例数据。假设您有 3 行。
- 你第一次运行通过循环,
i
是0
。你得到一个statement
和一个polarity
,但你不对它们做任何事情。 - 你第二次运行通过循环,
i
是1
。你得到一个statement
和一个polarity
,但你不对它们做任何事情。 - 你第三次运行通过循环,
i
是2
。你得到一个statement
和一个polarity
,但你不对它们做任何事情。 - 然后循环退出。
statement
和polarity
变量超出范围,因此它们是undefined
。与i
变量相同。
基本上,该循环不执行任何操作。然后我们到达这一行:
statements[i] = new Statement(polarity, statement);
但我们知道 i
、polarity
和 statement
是未定义的,所以您真正要做的是:
statements[undefined] = new Statement(undefined, undefined);
你说这个有用,但我很怀疑。你在这里做什么没有任何意义。该语句绝对属于 for 循环,这是我对
但是按照您现在的方式,数组中没有添加任何内容,除了未定义索引处的内容。那么我们就到了这一行:
for (var i = 0; i < statements.length; i++) {
statements[i].display();
}
现在,我敢打赌 statements.length
是 1,因为您在一个未定义的索引处有一些东西(也许那个索引是 i
的最后一个值,我不知道)。但是您肯定在索引 0
处没有任何内容。那么当你进入这个循环时,i
是 0
,但你在那个索引处没有任何东西。换句话说,statements[0]
是未定义的。所以内线真的是这样做的:
undefined.display();
这就是导致您出错的原因。解决第一个问题将消除此错误,因为您实际上是在向数组中添加内容。
此外,请注意以下几行:
// Was directed to add both 'text' statements
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
我给你的这段代码只是一个例子。你必须在这里做一些更智能的事情。我只是向您展示了如何访问 statement
数组的两个索引。您必须实际检查此数组的长度并循环遍历句子才能执行某些操作。那是什么完全取决于你想要发生什么。
关于一般调试
您似乎遇到了很多问题,因为您试图同时处理所有事情。如果您开始以更小的块工作,您会省去很多麻烦。与其尝试将此功能添加到您的大主草图中,不如尝试先让一个较小的示例草图工作?尝试对这些值进行硬编码,这样您就可以准确地看到 split()
函数发生了什么。使用 println()
语句来了解发生了什么。尝试一次添加所有内容只会让您和我们感到困惑。
请注意,这不是对 MCVE 的请求(因为我上次提到它时你很生气),但老实说,你能做的最好的帮助自己的事情就是从更小的步骤开始工作。
您也可以考虑切换到常规处理(Java 模式),因为它可以为您提供有关此类错误的更多信息。
我终于能够通过对代码进行一些简单的更改来解决此问题。一旦我想到它,它似乎非常明显,我完全不确定为什么我花了这么长时间才弄明白。
我首先更改 setup()
代码:
function setup() {
canvas = createCanvas(680, 420);
canvas.mousePressed(inWidth);
background(51);
noStroke();
// iterate over the table rows called in 'preload()' from .csv file
for (var i = 0; i < clContext.getRowCount(); i++) {
var statement = clContext.get(i, "statement");
var polarity = clContext.get(i, "polarity");
var stateSplit = split(statement, "<br>"); // split the statements in setup to avoid issues elsewhere
for (var j = 0; j < stateSplit.length; j++) {
var stateJoin = join(stateSplit, "\n"); // join the statements, inserting a line break, to make a new array
statements[i] = new Statement(polarity, stateJoin); // put this in the for loop (per @marton)
}
}
}
然后我修改了我的构造函数和原型显示函数如下:
摆脱了这个,因为它只分解了语句,但没有加入它们:
this.statement = split(statement, "<br>");
并将其替换为:
this.stateJoin = stateJoin;
然后我摆脱了这些:
text(this.statement[0], this.x, this.y);
text(this.statement[1], this.x, this.y+25);
并改用这个:
text(this.stateJoin, this.x, this.y)
瞧!感谢@marton 和@KevinWorkman 的建议。