【问题标题】:How to loop through functions by name in P5js / JavaScript如何在 P5js/JavaScript 中按名称循环函数
【发布时间】:2019-12-25 16:02:58
【问题描述】:

我正在开发一个需要最多十个输入框的基本 P5 程序。

所以我需要首先创建按钮实例,例如使用

  factor1Input = createInput(""); // create DOM element for input field
  factor1Input.position(leftMargin, topMargin + 50); // place button on screen
  factor1Input.changed(this.factor1update); // call function when value changes
  factor1Button = createButton('Update Factor'); // create DOM element for button
  factor1Button.position(100, 100); // position button

然后使用例如切换它们的可见性

    factor1Input.show(); // toggle display on
    factor1Button.show();

    factor1Input.hide(); // or toggle it off 
    factor1Button.hide();

但是因为我最多有 10 个,所以这将需要大量重复的代码。

所以我想创建一个类似的循环(例如,仅用于 show 函数);

    for (let i = 1; i < factorCount; i++){
      let fci = "factor" + i + "Input"; 
      let fcb = "factor" + i + "Button"; 

      fci.show(); 
      fcb.show(); 
    }

但我收到以下错误:

Uncaught TypeError: fci.show is not a function

这表明某种类型的不匹配,即我似乎不能只编译一个字符串,并将其识别为 JavaScript 函数。

有什么建议吗?

【问题讨论】:

  • 这被称为“投影”,应该不惜一切代价避免。您应该改为使用类,创建实例并将对它们的引用保存在数组中。这些因素是什么?是什么切换了可见性?

标签: javascript function loops p5.js


【解决方案1】:

fci 将是一个字符串,因此 String 类将没有方法 show,你会得到一个异常。而是

你可以这样写

var factorObject = {
  factor1Input:createInput("")
}
factorObject['factor1Input'].position(leftMargin, topMargin + 50);

为了表演

factorObject['factor1Input'].show();

在循环中

 for (let i = 1; i < factorCount; i++){
      let fci = "factor" + i + "Input"; 
      factorObject[fci].show(); 
  }

【讨论】:

    【解决方案2】:

    你的代码不工作的原因是因为你创建了一个字符串并试图像一个同名的变量一样调用它

    let fci = "factor" + i + "Input"; 
    fci.show(); // fci is just a string 'factor1Input', has nothing in common with factor1Input variable
    

    您应该使用数组Arrays,而不是将输入数字(例如索引)保留在名称中,让它成为数组中项目的索引

    const factorCount = 10
    const inputs = []
    const buttons = []
    
    // example of creating inputs and buttons in a loop, you can create them manually if you want,
    // but don't forget to .push them to respective array
    
    for (let i = 1; i < factorCount; i++){
      const input = createInput("");
      input.position(leftMargin, topMargin + 50 * i); // using index to calculate top margin
      input.changed((value) => this.factorUpdate(i, value)); // notice the change here
      inputs.push(input)
      const button = createButton('Update Factor');
      button.position(100, 100 + 50 * i); // also using index to calculate top margin
      buttons.push(button)
    }
    
    
    function showInput(index) {
      inputs[index].show()
      buttons[index].show()
    }
    
    function hideInput(index) {
      inputs[index].hide()
      buttons[index].hide()
    }
    
    showInput(3) // shows 3rd input and button
    hideInput(4) // hides 4th input and button
    

    还请注意我是如何更改您的 this.factor1update 方法调用的。就像您不想为 10 个元素使用 10 个单独的变量一样,您也不想使用 10 种方法来处理这 10 个元素的更改(如果有 10000 个元素怎么办?)。相反,创建一个方法factorUpdate,它将接收项目索引和更改的值并使用它来处理输入更改


    添加:

    for (let i = 0; i < factorCount; i++){ // changed 1 to 0 here, it was a typo
      const input = createInput("");
      input.position(leftMargin, topMargin + 50 * i);
      input.changed(() => factorUpdate(i)); // we call factorUpdate with index of an element
      inputs.push(input)
      const button = createButton('Update Factor');
      button.position(185, topMargin + 50 * i);
      buttons.push(button)
    }
    
    function factorUpdate(i, event){
      // argument i is now an index of unfocused input
      console.log("input index: " + i + ", value: " + inputs[i].value());
    }
    

    还要注意input.changed() 的工作原理:编辑输入,然后单击页面上的其他位置以取消焦点,这就是触发此事件的时间。考虑到这一点,这里的按钮实际上并没有做任何事情,因为没有分配给它们的点击侦听器

    【讨论】:

    • 实际上,Max,它已经很接近了,但我在这段代码中遇到了一些其他问题。你能看看吗? editor.p5js.org/knectar/sketches/07YcpXUzS 你会在第 18 行看到一个警告。然后看起来我在更新(例如)第一个输入字段后捕获数组元素值时做错了。
    • 这只是一个关于混淆语义的警告,但这完全没问题。但是还有另一个问题,在我的示例中,我将特定参数传递给 factorUpdate 函数,以便您可以使用它们来了解更新了哪个输入,但是在您的代码中您不使用它们,因此无论更新了什么事件,相同的factorUpdate 将始终运行并记录第一个输入。用简化的例子编辑了我的答案
    • 感谢 Max,现在按预期工作。看起来并不需要这么多更新按钮,editor.p5js.org/knectar/sketches/07YcpXUzS
    • 嗨 Max,快速提问,有没有办法将 lamda 函数重写为 lamda 函数?此外,对于function factorUpdate(i, event){ 行,代码在没有第二个“事件”参数的情况下工作。那个参数是必要的吗?
    • @ChrisAmato 是的,您也可以使用经典功能function() { factorUpdate(i) } 不,如果您不使用它,则不需要event 参数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    相关资源
    最近更新 更多