0

This is a kind of weird problem. Given the javascript below, I'm expecting the newFunctions object to contain functions that wrap an original object, however it's only running the last action that occurs in the loop. Shouldn't var actionToCall copy a reference to what currentAction is currently looking at, and not change when the loops iterate? I'm stumped here.

  var typeArray = {
    type1: {
      function1: function() {
        console.log("this is function 1");
      },
      function2: function() {
        console.log("this is function 2");
      }
    },
    type2: {
      somefunction: function() {
        console.log("this is some function")
      }
    },
    type3: {
      blah: function() {
        return;
      },
      moreBlah: function(something) {
        console.log(something);
      },
      evenMore: function() {
        console.log("I'm last!");
      }
    }
  },
      index,
      typeIndex,
      currentType,
      actionIndex,
      currentAction,
      newFunctions = {};

  for(typeIndex in typeArray) {
    currentType = typeArray[typeIndex];
    for(actionIndex in currentType) {
      currentAction = currentType[actionIndex];

      console.log(currentAction.toString());

      newFunctions[actionIndex] = function() {
        var actionToCall = currentAction;

        console.log("about to run action");

        actionToCall.call(this);

        console.log("action has been called");
      }
    }
  }

  console.log(newFunctions);

  for(index in newFunctions) {
    (newFunctions[index])();
  }

1 Answer 1

1

It's because actionToCall is being assigned to currentAction.

Since currentAction is global it's value keeps changing as the loop iterates.

When the loop ends, currentAction is assigned to evenMore.

Here's the fix using a self execution function to induce scope.

var typeArray = {
    type1: {
        function1: function() {
            console.log("this is function 1");
        },
        function2: function() {
            console.log("this is function 2");
        }
    },
    type2: {
        somefunction: function() {
            console.log("this is some function")
        }
    },
    type3: {
        blah: function() {
            return;
        },
        moreBlah: function(something) {
            console.log(something);
        },
        evenMore: function() {
            console.log("I'm last!");
        }
    }
},
index,
typeIndex,
currentType,
actionIndex,
currentAction,
newFunctions = {};

for(typeIndex in typeArray) {
    currentType = typeArray[typeIndex];
    for(actionIndex in currentType) {
        currentAction = currentType[actionIndex];

        console.log(currentAction.toString());

        //induce scope here so actionToCall keeps the current value of currentAction.
        (function(){

            var actionToCall = currentAction;
            newFunctions[actionIndex] = function() {


                console.log("about to run action");

                actionToCall.call(this);

                console.log("action has been called");
            }
        })();
    }
}

console.log(newFunctions);

for(index in newFunctions) {
    (newFunctions[index])();
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.