dynamically generate function in object

Posted on
  • Hello,
    I am trying to create a Bangle.js app for my gym training plan.
    I have an interface for the app loader where I create the training plan, this is an Array of json objects.
    Now I want to create a menu, where I can select a machine which has not been finished.

    function showMenu(){
      function createMenuItems(){
        menuObjekt = {};
        menuObjekt[""] = {"title" : "machines left"};
        for (var i = 0; i < tempArray.length; i++){
          if (tempArray[i].finished == false){
            key = tempArray[i].machine;
                    
            menuObjekt[key] = function(){showSettings(tempArray[i])};
          }
          
        }
        menuObjekt.Exit = function() { E.showMenu();};
        return menuObjekt;
      }
      
      var mainmenu = createMenuItems();
      console.log(mainmenu);
      E.showMenu(mainmenu);
    }
    

    The keys are shown correct, but the function to get the settings view does not work.
    The output for consol.log(mainmenu); is:

    {
      "": {
        "title": "machines left"
       },
      "machine 1": function () {showSettings(tempArray[i])},
      "machine 2": function () {showSettings(tempArray[i])},
      "machine 3": function () {showSettings(tempArray[i])},
      "Exit": function () {E.showMenu();}
     }
    
    
    

    Why is the index not replaced?
    I tried a lot of stuff, but don't understand my problem.
    Neither my programming skills nor my English are very good, so I don't get the problem.
    The web ide is warning me, that functions declared within loops may lead to confusing semantics, but I don't see another way?
    There may be a different amount of machines I want to train, and I want only the machines to be in the machines I haven't finished.

    Thank you in advance for your help and patience.
    Tobi

  • Why is the index not replaced?

    This is quite a common thing. The code itself is stored and executed as-is, but the variable i that it references is the same one each time - and it changes.

    The usual solution for this is to use forEach to iterate over the array - it means that a new function is called for each menu item. That function will then have an argument i which is different for each call.

    tempArray.forEach(function(m, i) {
          if (m.finished == false)
            menuObjekt[m.machine] = function(){showSettings(m)};
          }
    });
    

    Hope that helps!

  • @Gordon, you say in other words that because in line #1 a new code-object - reference-object m (pointing to/referencing related machine object) - is created and then used in a function code-object and held in the array, the reference to m is held on to until the whole menuObject disappears / garbage collected... (Btw, since menuObject is not declared in function, its first use declares it as global and it survives the end of showMenu() function, and stays alive until set again as a new object (menuObjekt = {}), then the previous 'content' is garbage collected.

  • Why is the index not replaced?

    the function inside menuObjekt[key] = function(){showSettings(tempArray[i])}; is just defined but not evaluated inside the loop. Only later when function is called it is really evaluated so only then tempArray and i variable values are read.

    You would need to store value of tempArray[i] into the menuObjekt or somewhere else directly in the loop.

  • Hey,
    yes, that helped. Thank you. For your answer and this great project.
    Cheers

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

dynamically generate function in object

Posted by Avatar for Primata @Primata

Actions